
2.3.2 随机访问文件
RandomAccessFile类可以在文件中的任何位置查找或写入数据。磁盘文件都是随机访问的,但是与网络套接字通信的输入/输出流却不是。你可以打开一个随机访问文件,只用于读入或者同时用于读写,你可以通过使用字符串“r”(用于读入访问)或“rw”(用于读入/写出访问)作为构造器的第二个参数来指定这个选项。

当你将已有文件作为RandomAccessFile打开时,这个文件并不会被删除。
随机访问文件有一个表示下一个将被读入或写出的字节所处位置的文件指针,seek方法可以用来将这个文件指针设置到文件中的任意字节位置,seek的参数是一个long类型的整数,它的值位于0到文件按照字节来度量的长度之间。
getFilePointer方法将返回文件指针的当前位置。
RandomAccessFile类同时实现了DataInput和DataOutput接口。为了读写随机访问文件,可以使用在前面小节中讨论过的诸如readInt/writeInt和readChar/writeChar之类的方法。
我们现在要剖析一个将雇员记录存储到随机访问文件中的示例程序,其中每条记录都拥有相同的大小,这样我们可以很容易地读入任何记录。假设你希望将文件指针置于第三条记录处,那么你只需将文件指针置于恰当的字节位置,然后就可以开始读入了。

如果你希望修改记录,然后将其存回到相同的位置,那么请切记要将文件指针置回到这条记录的开始处:

要确定文件中的字节总数,可以使用length方法,而记录的总数则是用字节总数除以每条记录的大小。

整数和浮点值在二进制格式中都具有固定的尺寸,但是在处理字符串时就有些麻烦了,因此我们提供了两个助手方法来读写具有固定尺寸的字符串。
writeFixedString写出从字符串开头开始的指定数量的码元(如果码元过少,该方法将用0值来补齐字符串)。

readFixedString方法从输入流中读入字符,直至读入size个码元,或者直至遇到具有0值的字符值,然后跳过输入字段中剩余的0值。为了提高效率,这个方法使用了StringBuilder类来读入字符串。


我们将writeFixedString和readFixedString方法放到了DataIO助手类的内部。
为了写出一条固定尺寸的记录,我们直接以二进制方式写出所有的字段:

读回数据也很简单:

让我们来计算每条记录的大小:我们将使用40个字符来表示姓名字符串,因此,每条记录包含100个字节:
·40字符=80字节,用于姓名。
·1 double=8字节,用于薪水。
·3 int=12字节,用于日期。
程序清单2-2中所示的程序将三条记录写到了一个数据文件中,然后以逆序将它们从文件中读回。为了高效地执行,这里需要使用随机访问,因为我们需要首先读入第三条记录。
程序清单2-2 randomAccess/RandomAccessTest.java



java.io.RandomAccessFile 1.0
·RandomAccessFile(String file,String mode)
·RandomAccessFile(File file,String mode)
参数:file 要打开的文件
mode “r”表示只读模式;“rw”表示读/写模式;“rws”表示每次更新时,都对数据和元数据的写磁盘操作进行同步的读/写模式;“rwd”表示每次更新时,只对数据的写磁盘操作进行同步的读/写模式
·long getFilePointer()
返回文件指针的当前位置。
·void seek(long pos)
将文件指针设置到距文件开头pos个字节处。
·long length()
返回文件按照字节来度量的长度。