Java IO : RandomAccessFile

405 查看

RandomAccessFile概览

对文件的读取,既可以按顺序,也可以以任意顺序来读取。
RandomAccessFile提供这样一种功能。其保存一个指向当前文件位置的指针,可以通过调整指针的位置,读取一个文件中任意的内容。通过一段简单的代码来有个大体的认识:

RandomAccessFile raf = new RandomAccessFile("abc.log", "r");
int logIndex = 10;
raf.seek(logIndex);
//接下来通过raf进行文件操作

构造器

RandomAccessFile提供了两个构造器

RandomAccessFile(File file, String mode)
RandomAccessFile(String path, String mode)

模式

通过RandomAccessFile打开一个文件需要指定打开的模式,构造参数中的mode有四种模式可以选择:

  1. "r",以只读的方式打开一个已存在的文件,不可对文件进行写操作。

  2. "rw",以读写的方式打开一个已存在的文件,若文件不存在,则创建一个,可对该文件进行读写操作。

  3. "rwd",除了具有"rw"的特点外,这个模式要求对文件内容的每一个更新都会同步更新至底层的物理存储。

  4. "rws",除了具有"rw"的特点外,这个模式要求对文件内容和文件元数据的每一个更新都会同步更新至底层的物理存储。

文件的元数据并非指文件的内容本身,文件的大小以及文件的最后修改时间等等算是元数据的一部分

显然,如果指定了rwdrws模式,那么对于文件的操作将会相对比较慢一些。

读写

RandomAccessFile内部维护了一个指针,指向当前读取或者写入的位置,当通过RandomAccessFile打开一个已存在的文件或者创建一个新文件时,指针自动指向下标为0的位置。进行写入操作时,如果指针已经指向文件的末尾,那么文件的大小将会被扩大。

当需要进行读取或者写入时,首先通过void seek(long pos)将文件的指针指向你想要读取或写入的位置,读取时有以下常用的方法可以进行读取:

  • int read() //读取下一个字节

  • int read(byte[] b) //将读取的字节装入b数组中

  • char readChar() //读取两个字节,并将其转型为char类型

  • int readInt() //读取四个字节,并将其转型为int类型

写入时有以下方法:

  • void write(int b) //将b的低八位写入

  • void writeChars(String s) //将字符串s所代表的字节写入

  • void write(byte[] b) //将字节数组b写入

  • void writeInt(int i) //写入4个字节的i

除了读取写入的方法外,setLength(long newLength)方法可以设置文件的大小,如果newLength小于当前文件大小,那么文件将会被截肢,反之,文件将会被扩大到newLength。

FileDescriptor

值得注意的是,RandomAccessFile提供了一个FileDescriptor getFD()方法获取文件所对应的文件描述符对象,文件描述符代表是一种平台独立的文件描述结构,通过这个描述符可以对文件进行一些特殊的操作。

FileDescriptor定义了sync()方法,与之前提到的"rwd"和"rwd"一样,sync方法用来告诉操作系统将缓冲区的内容全部刷到物理的存储上。如果没有指定rwd或者rws模式,那么对文件的写入将会暂时存储于操作系统层面的缓冲区里面,当缓冲区满时,操作系统才会将内容刷至物理磁盘,通过sync()方式可以让操作系统对每一次写入操作都同步刷新至物理存储中,以下为一个例子:

RandomAccessFile raf = new RandomAccessFile("abc.log", "rw");
//这里的模式不是rwd或者rws
FileDescriptor fd = raf.getFD();
raf.write(...);
// 通过fd的sync方法,可以让写入操作同步地刷新至物理存储
fd.sync();
raf.close();