【JavaIO流】RandomAccessFile类

RandomAccessFile类

RandomAccessFile类创建的流称作随机流,与前面的输入输出流不同的是,RandomAccessFile类既不是InputStream类的子类,也不是OutputStream类的子类。但是RandomAccessFile类创建的流的指向既可以作为流的源,也可以作为流的目的地,换句话说,当准备对一个文件进行读写操作时,可以创建一个指向该文件的随机流即可,这样既可以从这个流中读取文件的数据,也可以通过这个流写入数据到文件。并且通过该类可以访问文件任意位置的信息。

构造函数

/**
 * 参数name用来确定一个文件名,给出创建的流的源,也是流的目的地;
 * 参数mode取r(只读)或rw(可读写)等访问权限,决定创建的流对文件的访问权力;
 */
public RandomAccessFile(String name, String mode);

/**
 * 参数file是一个File对象,给出创建的流的源,也是流的目的地;
 * 参数mode取r(只读)或rw(可读写)等访问权限,决定创建的流对文件的访问权力;
 */
public RandomAccessFile(File file, String mode);
  • 这里对第二个参数mode(模式)作详细说明 :表示了以何种方式打开文件,共有4种模式:"r""rw""rws""rwd"
    • "r":以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException
    • "rw":打开以便读取和写入。
    • "rws":打开以便读取和写入。相对于 "rw""rws" 还要求对“文件的内容”或“元数据”的每个更新都同步写入到基础存储设备。
    • "rwd":打开以便读取和写入,相对于 "rw""rwd" 还要求对“文件的内容”的每个更新都同步写入到基础存储设备。

什么是“元数据”,即metadata?
英文解释如下:
The definition of metadata is “data about other data.” With a file system, the data is contained in its files and directories, and the metadata tracks information about each of these objects: Is it a regular file, a directory, or a link? What is its size, creation date, last modified date, file owner, group owner, and access permissions?
大致意思是:
metadata是“关于数据的数据”。在文件系统中,数据被包含在文件和文件夹中;metadata信息包括:“数据是一个文件,一个目录还是一个链接”,“数据的创建时间(简称ctime)”,“最后一次修改时间(简称mtime)”,“数据拥有者”,“数据拥有群组”,“访问权限”等等。

"rw", “rws”, “rwd” 的区别

  • 当操作的文件是存储在本地的基础存储设备上时(如硬盘,NandFlash等),"rws""rwd""rw" 才有区别。
  • 当模式是 "rws" 并且 操作的是基础存储设备上的文件;那么,每次“更改文件内容(如write()写入数据)” 或 “修改文件元数据(如文件的mtime)”时,都会将这些改变同步到基础存储设备上。
  • 当模式是 "rwd" 并且 操作的是基础存储设备上的文件;那么,每次“更改文件内容(如write()写入数据)”时,都会将这些改变同步到基础存储设备上。
  • 当模式是 "rw" 并且 操作的是基础存储设备上的文件;那么,关闭文件时,会将“文件内容的修改”同步到基础存储设备上。至于,“更改文件内容”时,是否会立即同步,取决于系统底层实现。

常用方法

关键成员变量以及方法:

  • fileponiter:文件指针,用来标记当前读取或者写入的位置。
  • getFileponiter():返回当前文件指针的位置。
  • seek():设置当前文件指针的位置。

其他常用方法:

【JavaIO流】RandomAccessFile类_第1张图片

  • 需要注意的是,RandomAccessFile流的readLine()方法在读取含有非ASCII字符的文件时(例如含有汉字的文件)会出现“乱码”现象,因此,需要把readLine()方法读取的字符串用“iso-8859-1”重新编码存放到byte数组中,然后再用当前机器的默认编码将该数组转化为字符串。操作如下:
//1、读取
String str = in.readLine();
//2、用“iso-8859-1”重新编码
byte[] bytes = str.getBytes("iso-8859-1");
//3、使用当前机器的默认编码将字符数组转化为字符串
String content = new String(bytes);

代码示例

public class R_A_FileTest {
     
    public static void main(String[] args) {
     
        RandomAccessFile ra = null;
        try {
     
            //按照字节操作,第二个参数是文件的打开方式
            ra = new RandomAccessFile("D:\\Java文件IO\\Test\\b.txt", "rw");
            /**
             * 随机读取
             */
//            int length = (int)ra.length(); //获取文件长度
//            Random random = new Random();
//            int pos = random.nextInt(length);
//            while (pos >= 0 && pos < length) {
     
//                ra.seek(pos);
//                System.out.print((char) ra.read());
//                pos = pos + 1;
//            }

            /**
             * 尾部写入
             */
//            int length = (int)ra.length(); //获取文件长度
//            int pos = length;
//            String str = " i love java ";
//            ra.seek(pos);
//            ra.writeChars(str);
//            length = (int)ra.length(); //获取文件长度
//            pos = 0;
//            while (pos >= 0 && pos < length) {
     
//                ra.seek(pos);
//                System.out.print((char) ra.read());
//                pos = pos + 1;
//            }

            /**
             * 随机写入
             */
            ra.seek(2);
            byte[] b = new byte[10];
            int len;
            StringBuffer str = new StringBuffer();
            while ((len = ra.read(b))!= -1){
     
                str.append(new String(b,0,len));
            }
            ra.seek(2);
            ra.write("hhh".getBytes());
            ra.write(str.toString().getBytes());


//            String write = "Hello World!";
//            ra.writeChars(write);
//            ra.seek(0);
//            long length = ra.length(); //获取文件长度
//            String str = ra.readLine();
//            System.out.println("原文本为:" + str);
//            System.out.println("逆置后为:");
//            long pos = length - 1;
//            while (pos >= 0) {
     
//                ra.seek(pos);
//                System.out.print((char) ra.read());
//                pos = pos - 1;
//            }
//            System.out.println();
//            ra.seek(2); //skip
//            ra.getFilePointer(); //获取当前光标位置
        } catch (FileNotFoundException e) {
     
            e.printStackTrace();
        } catch (IOException e) {
     
            e.printStackTrace();
        } finally {
     
            if (ra != null) {
     
                try {
     
                    ra.close();
                } catch (IOException e) {
     
                    e.printStackTrace();
                }
            }
        }
    }
}

注意:

  • 因为RandomAccessFile类的 write() 方法,是在 filepointer 的位置覆盖写入,因此不能实现在任意位置去插入数据。

你可能感兴趣的:(JavaIO流)