目前,我们已经使用了顺序问价(sequential file),即必须以线性方式,逐字节访问的文件.然而,Java也允许以随机顺序来访问文件内容.为此,要使用封装有随机访问文件的RandomAccessFile.RandomAccessFile不是从InputStream或OutputStream派生而来的.相反,他实现了定义IO基本方法的接口DataInput和DataOutput.他还支持定位请求,即可以在文件中定位文件指针(file pointer).我们使用的构造函数如下所示:
RandomAccessFile(String fileName,string access) throws FileNotFoundException
这里,fileName中存储的是被传入的文件的名称,access确定了允许的文件访问类型.如果是”r”,文件只能读不能写.如果是”rw”,文件既可以读,又可以写.
这里的seek()方法用于设置文件中文件指针的当前位置:
void seek(long newPos) throws IOException
这里,newPos指定从文件开头进行计算,以字节计数的文件指针的新位置.在调用seek()以后,下一个读或写操作将在新的文件位置发生.
RandomAccessFile实现了read()和write()方法,以及DataInput和DataOutput接口,这就意味着读写基本类型的方法(如readIn()和writeDouble()是有效的)
下面是演示随机访问IO的一个示例.他向文件写入6个double类型的数据,并将他们已无序顺序读回:
public static void main(String args[]) throws IOException { double data[] = {19.4,10.1,123.34,3.2,43.2,34.3,432.2,2434.3}; double d; try(RandomAccessFile raf = new RandomAccessFile("ramdom.dat","rw")) { for(int i=0;i<data.length;i++) { raf.writeDouble(data[i]); } raf.seek(0); d = raf.readDouble(); System.out.println(d); raf.seek(8); d = raf.readDouble(); System.out.println(d); raf.seek(8*3); d = raf.readDouble(); System.out.println(d); System.out.println("Here is every other value:"); for(int i=0;i<data.length;i++) { raf.seek(i*8); d = raf.readDouble(); System.out.println(d); } } catch(IOException exc) { System.out.println("IO Error"); } }
输出:
19.4 10.1 3.2 Here is every other value: 19.4 10.1 123.34 3.2 43.2 34.3 432.2 2434.3
注意每个值是如何定位的.因为每一个double值都是8字节长,所以每个值都以8字节为界限.因此,第1个值定位在0,而第二个值就从字节8处开始,第三个值从字节16处开始,依次类推,读取第4个值时,程序就应该寻找字节24的位置.
问:在阅读JDK提供了文档时,注意有一个名为Console的类,可以使用他执行基于控制台的IO吗?
答:简单的回答是可以.console类是JDK6添加的,用来从控制台读写.Console只是提供了方便,因为他的大多数功能都可以通过System.in和System.out获得.但是,使用他可以简化某些类型的控制台交互,尤其是在从控制台读取字符串时.
Console类没有提供构造函数.console对象通过调用System.console()获得,如下所示:
static Console console()
如果控制台可用,将返回一个对控制台的引用;否则,返回null.控制台不会在所有情况下都可用,例如当程序作为后台任务运行时.因此,如果返回null,就说明无控制台IO可用.
console定义了一些执行IO的方法,如readLine()和printf(),他还定义了一个readPassword()方法,该方法用来获得密码,可以让应用读取密码,而不必回显键盘输入.还可以获得一个附加到控制台的对reader和writer的引用.总之,Console是一个对某些类型的引用程序有用的类.