RandomAccessFile是一个颇有用的类,能够将字节流写入到磁盘文件中,对应的也能够从磁盘文件中读取出字节流,在API中关于RandomAccessFile的描述以下:java
此类的实例支持对随机访问文件的读取和写入。随机访问文件的行为相似存储在文件系统中的一个大型 byte 数组。存在指向该隐含数组的光标或索引,称为文件指针;输入操做从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。若是随机访问文件以读取/写入模式建立,则输出操做也可用;输出操做从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾以后的输出操做致使该数组扩展。该文件指针能够经过 getFilePointer
方法读取,并经过 seek
方法设置。数组
一般,若是此类中的全部读取例程在读取所需数量的字节以前已到达文件末尾,则抛出 EOFException
(是一种 IOException
)。若是因为某些缘由没法读取任何字节,而不是在读取所需数量的字节以前已到达文件末尾,则抛出 IOException
,而不是 EOFException
。须要特别指出的是,若是流已被关闭,则可能抛出IOException
。dom
如下是两个RandomAccessFile的写入和读取的简单例子:编码
一、 将字节流写入到磁盘中spa
private static void testCreateFile(){ String directory = “D:/program/test”; String name = “t.gen”; File f = new File(directory, name); RandomAccessFile file = null; try { file = new RandomAccessFile(f, “rw”); byte[] b = {5,10,15,20}; try { //若是没有这行,文件也会生成,只是文件为空 file.write(b,0,4); } catch (IOException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { e.printStackTrace(); }finally{ if (null!=file){ try { file.close(); } catch (IOException e) { e.printStackTrace(); } } } }
二、 从磁盘文件中读取字节流
private static void testReadFile(){ String directory = “D:/program/luceneDemo3.0/test”; String name = “t.gen”; File f = new File(directory, name); RandomAccessFile file = null; try { file = new RandomAccessFile(f, “rw”); byte[] b = new byte[4]; try { long len = file.length(); file.read(b); //设置要读取的字节位置 file.seek(1); System.out.println(file.readByte()+”>>FilePointer>>”+file.getFilePointer()); for (int i=0;i<b.length;i++){ System.out.println(“>>>”+b[i]); } } catch (IOException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { e.printStackTrace(); }finally{ if (null!=file){ try { file.close(); } catch (IOException e) { e.printStackTrace(); } } } }
说明:指针
一、 这个类依我看来,用来处理字节流(byte)是很好的,若是用来处理字符(串)或其余数据类型,好比int、long,我试了感受效果并很差,尤为是处理中文字符串的时候,那简直就是一个灾难,你会又碰上纠缠不清的乱码!code
二、 seek(long pos)方法orm
是在读取的时候用来设置读取到哪个字节的,好比在例子中有5,10,15,20字节,在byte数组中分别对应0、一、二、3位置,一样在文件file = new RandomAccessFile(f, “rw”);中,也对应着0、一、二、3位置,因此若是设置file.seek(1);就表示经过file.readByte()读取的时候,读取的是第1位置的数据,也就是10了。对象
三、 getFilePointer()方法索引
在经过上面说的seek(long pos)设置后,getFilePointer()获得的就是当前文件中的字节位置,也就是所说的偏移量了。好比在这个例子中,getFilePointer()的值就是1.
四、文件模式
“r” 以只读方式打开。调用结果对象的任何 write 方法都将致使抛出 IOException。
“rw” 打开以便读取和写入。若是该文件尚不存在,则尝试建立该文件。
“rws” 打开以便读取和写入,对于 “rw”,还要求对文件的内容或元数据的每一个更新都同步写入到底层存储设备。
“rwd” 打开以便读取和写入,对于 “rw”,还要求对文件内容的每一个更新都同步写入到底层存储设备。
附录:
void | close() 关闭此随机访问文件流并释放与该流关联的全部系统资源。 |
FileChannel | getChannel() 返回与此文件关联的惟一 FileChannel 对象。 |
FileDescriptor | getFD() 返回与此流关联的不透明文件描述符对象。 |
long | getFilePointer() 返回此文件中的当前偏移量。 |
long | length() 返回此文件的长度。 |
int | read() 今后文件中读取一个数据字节。 |
int | read(byte[] b) 将最多 b.length 个数据字节今后文件读入 byte 数组。 |
int | read(byte[] b, int off, int len) 将最多 len 个数据字节今后文件读入 byte 数组。 |
boolean | readBoolean() 今后文件读取一个 boolean。 |
byte | readByte() 今后文件读取一个有符号的八位值。 |
char | readChar() 今后文件读取一个字符。 |
double | readDouble() 今后文件读取一个 double。 |
float | readFloat() 今后文件读取一个 float。 |
void | readFully(byte[] b) 将 b.length 个字节今后文件读入 byte 数组,并从当前文件指针开始。 |
void | readFully(byte[] b, int off, int len) 将正好 len 个字节今后文件读入 byte 数组,并从当前文件指针开始。 |
int | readInt() 今后文件读取一个有符号的 32 位整数。 |
String | readLine() 今后文件读取文本的下一行。 |
long | readLong() 今后文件读取一个有符号的 64 位整数。 |
short | readShort() 今后文件读取一个有符号的 16 位数。 |
int | readUnsignedByte() 今后文件读取一个无符号的八位数。 |
int | readUnsignedShort() 今后文件读取一个无符号的 16 位数。 |
String | readUTF() 今后文件读取一个字符串。 |
void | seek(long pos) 设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操做。 |
void | setLength(long newLength) 设置此文件的长度。 |
int | skipBytes(int n) 尝试跳过输入的 n 个字节以丢弃跳过的字节。 |
void | write(byte[] b) 将 b.length 个字节从指定 byte 数组写入到此文件,并从当前文件指针开始。 |
void | write(byte[] b, int off, int len) 将 len 个字节从指定 byte 数组写入到此文件,并从偏移量 off 处开始。 |
void | write(int b) 向此文件写入指定的字节。 |
void | writeBoolean(boolean v) 按单字节值将 boolean 写入该文件。 |
void | writeByte(int v) 按单字节值将 byte 写入该文件。 |
void | writeBytes(String s) 按字节序列将该字符串写入该文件。 |
void | writeChar(int v) 按双字节值将 char 写入该文件,先写高字节。 |
void | writeChars(String s) 按字符序列将一个字符串写入该文件。 |
void | writeDouble(double v) 使用 Double 类中的 doubleToLongBits 方法将双精度参数转换为一个 long,而后按八字节数量将该 long 值写入该文件,先定高字节。 |
void | writeFloat(float v) 使用 Float 类中的 floatToIntBits 方法将浮点参数转换为一个 int,而后按四字节数量将该 int 值写入该文件,先写高字节。 |
void | writeInt(int v) 按四个字节将 int 写入该文件,先写高字节。 |
void | writeLong(long v) 按八个字节将 long 写入该文件,先写高字节。 |
void | writeShort(int v) 按两个字节将 short 写入该文件,先写高字节。 |
void | writeUTF(String str) 使用 modified UTF-8 编码以与机器无关的方式将一个字符串写入该文件。 |
------------------------------------------------------------------------------------------
import java.io.File; import java.io.RandomAccessFile; import java.io.IOException; public class DemoRandomAccessFile { private static void doAccess() { try { File file = new File("DemoRandomAccessFile.out"); RandomAccessFile raf = new RandomAccessFile(file, "rw"); // Read a character byte ch = raf.readByte(); System.out.println("Read first character of file: " + (char)ch); // Now read the remaining portion of the line. // This will print out from where the file pointer is located // (just after the '+' character) and print all remaining characters // up until the end of line character. System.out.println("Read full line: " + raf.readLine()); // Seek to the end of file raf.seek(file.length()); // Append to the end of the file raf.write(0x0A); raf.writeBytes("This will complete the Demo"); raf.close(); } catch (IOException e) { System.out.println("IOException:"); e.printStackTrace(); } } public static void main(String[] args) { doAccess(); } } }
------------------------------------------------------------------------------------------
RandomAccessFile 类的主要功能是完成文件的随机读取操做,能够随机读取文件中指定位置的数据。若是要实现随机读取,则数据在文件中保存的长度必需要一致,不然没法实现该功能。 RandomAccessFile实现了 DataOutput、 DataInput 、 Closeable 接口。 RandomAccessFile的构造方法: public RandomAccessFile(File file,String mode) throes FileNotFoundException 该构造方法须要接收一个File 的实例,和一个操做模式: 只读模式:r 只写模式:w 读写模式:rw ,此模式若是文件不存在,则自动建立文件 一、 使用RandomAccessFile 进行写入操做 写入操做方法主要为从DataOutput 接口中实现的一系列 writeXxx() 方法,如:
package com.chenzehe.test.io; import java.io.File; import java.io.RandomAccessFile; public class RandomAccessFileDemo { public static void main(String[] args) throws Exception { File file = new File("D:" + File.separator + "demo.txt"); RandomAccessFile radomAccessFile = new RandomAccessFile(file, "rw"); // 写入第一条数据 String name = "first "; int age = 30; radomAccessFile.writeBytes(name); radomAccessFile.writeInt(age); // 写入第二条数据 name = "second "; age = 31; radomAccessFile.writeBytes(name); radomAccessFile.writeInt(age); // 写入第三条数据 name = "third "; age = 32; radomAccessFile.writeBytes(name); radomAccessFile.writeInt(age); radomAccessFile.close();//关闭文件 } }二、 RandomAccessFile读操做 RandomAccessFile读操做是从实现 DataInput 接口方法而来,有一系列的 readXxx() 方法,能够读取各类类型的数据,有下面两种方法控制读取位置: 回到读取点:public void seek(long pos) throws IOException 跳过n 个字节数: public void skipBytes(int n) throws IOException 如
package com.chenzehe.test.io; import java.io.File; import java.io.RandomAccessFile; public class RandomAccessFileDemo { public static void main(String[] args) throws Exception { File file = new File("D:" + File.separator + "demo.txt"); RandomAccessFile radomAccessFile = new RandomAccessFile(file, "rw"); byte[] b = new byte[10]; String name = null; int age = 0; radomAccessFile.skipBytes(14);// 跳过第一我的的信息 System.out.println("第二我的的信息为:"); for (int i = 0; i < 10; i++) { b[i] = radomAccessFile.readByte(); } age = radomAccessFile.readInt();// 读取数字 System.out.println("姓名:" + new String(b)); System.out.println("年龄:" + age); radomAccessFile.seek(0);// 回到第一我的信息开始处 System.out.println("第一我的的信息为:"); for (int i = 0; i < 10; i++) { b[i] = radomAccessFile.readByte(); } age = radomAccessFile.readInt();// 读取数字 System.out.println("姓名:" + new String(b)); System.out.println("年龄:" + age); radomAccessFile.skipBytes(14);// 此时文件读取指针在第一我的信息末,跳过第二我的信息 System.out.println("第三我的的信息为:"); for (int i = 0; i < 10; i++) { b[i] = radomAccessFile.readByte(); } age = radomAccessFile.readInt();// 读取数字 System.out.println("姓名:" + new String(b)); System.out.println("年龄:" + age); radomAccessFile.close();// 关闭文件 } }