java编程笔记16 随机访问文件类RandomAccessFile

文件的随机访问主要是通过RandomAccessFile来完成,它使用seek()方法从文件中的一个记录移动到下一个记录进行读或者写,而不需要知道总共多少个记录。它不需要把所有的记录全部装进内存再进行读写,对于访问大文件来说,这是一种高效的选择。

构造函数:两种方法来制定对应的文件:字符串路径和File

构造方法摘要
RandomAccessFile(File file, String mode)
          创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定。
RandomAccessFile(String name, String mode)
          创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称。

常用方法:

方法摘要
 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 编码以与机器无关的方式将一个字符串写入该文件。

测试程序:将4条person数据按照一定的格式(各字段定长写入到文件),然后随机遍历整个文件,输出所有的记录。然后找到包含关键字的的记录。

package FileOperation;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;

public class FileRandomAccess {
	
	/** 姓名在文件中的长度 */
	public static final int NAME_LENGTH = 100;
	/** 年龄在文件中的长度 */
	public static final int INT_LENGTH = 8;
	public static final int DESCRIPTION_LENGTH = 200;
	/** 每条 Person 记录在文件中的长度 */
	public static final int PERSON_LENGTH = NAME_LENGTH + INT_LENGTH + DESCRIPTION_LENGTH;

	//Person内部类
	static class Person{
		
		public String name;
		public int age;
		public String description;
		
		public Person(String name, int age, String description){
			this.name = name;
			this.age = age;
			this.description = description;
		}
		
		public String toString(){
			return "Person[name=\"" + name + "\", age=\"" + age + "\", description=\"" + description + "\"]";
		}		
	}

	
	//定义一个Person类型的数组
	static Person[] person = new Person[] { 
						new Person("杜甫", 45, "唐朝现实主义诗人"),
						new Person("爱因斯坦", 20, "伟大的物理学家,提出相对论理论。"), 
						new Person("李白", 20, "唐朝浪漫主义诗人"), 
						new Person("曹雪芹", 47, "《红楼梦》作者"), 
			};
	
	
	//main函数
	public static void main(String[] args) throws IOException{
		
		//构造一个随机访问类的file对象
		RandomAccessFile file = new RandomAccessFile("C:\\person.dat", "rw");
		
		// 初始化数据 根据初始化数据设置文件长度
		file.setLength(person.length * PERSON_LENGTH);
		for(int i=0; i<person.length; i++){
			writePerson(file, person[i]);//调用writePerson
		}
		
		System.out.println("\r\n列出文件中所有的数据:");
		Person[] allPersons = listAllPerson(file);//调用listAllPerson返回一个person数组
		for(int i=0; i<allPersons.length; i++){
			System.out.println(allPersons[i]);
		}
		
		
		System.out.println("\r\n在文件中查找关键字 雪,结果如下:");
		
		Person p = findPerson(file, "雪");//调用findPerson查找file里的keyword
		
		System.out.println("找到结果:" + p);
		
		file.close();
		
	}
	
	
	// 写 String 类型数据,要注意写String和写int的区别,
	public static void writeString(RandomAccessFile file, String name, int fieldLength) throws IOException{
		file.writeUTF(name);
		int length = name.getBytes("UTF-8").length;
		file.skipBytes(fieldLength - length);//跳过没有用完的字节,保持对齐
	}
	
	
	// 写 int 类型数据
	public static void writeInt(RandomAccessFile file, int age) throws IOException{
		file.writeInt(age);
	}
	
	
	//写person对象(写 String,写 int )
	public static void writePerson(RandomAccessFile file, Person person) throws IOException{
		writeString(file, person.name, NAME_LENGTH);
		writeInt(file, person.age);
		writeString(file, person.description, DESCRIPTION_LENGTH);
	}
	
	
	// 读 String 类型数据
	public static String readString(RandomAccessFile file, int fieldLength) throws IOException{
		String name = file.readUTF();
		int length = name.getBytes("UTF-8").length;
		file.skipBytes(fieldLength - length);
		return name;
	}
	
	
	// 读 int 类型数据
	public static int readInt(RandomAccessFile file) throws IOException{
		return file.readInt();
	}
	
	
	//读person对象(读 String,读 int)
	public static Person readPerson(RandomAccessFile file) throws IOException {
		
		// 找到文件头了
		if(file.getFilePointer() >= file.length()){
			return null;
		}
		
		return new Person(
				readString(file, NAME_LENGTH), 	// name
				readInt(file), 	// age
				readString(file, DESCRIPTION_LENGTH)	// description
				);
	}
	
	
	
	// 列出数据文件中的所有的数据
	public static Person[] listAllPerson(RandomAccessFile file) throws IOException {
		List list = new ArrayList();
		file.seek(0);

		while(true){
			Person person = readPerson(file);
			if(person == null)
				break;
			list.add(person);
		}
		Person[] person = new Person[list.size()];
		list.toArray(person);
		return person;
	}
	
	
	// 查找符合条件的数据
	public static Person findPerson(RandomAccessFile file, String keyword) throws IOException {
		// 从开始寻找记录
		file.seek(0);
		while(true){
			Person person = readPerson(file);//每次读一个person,注意每次seek都要往后移动
			if(person == null)
				break;
			if(person.name.contains(keyword)){
				return person;
			}
		}
		return null;
	}
	
}

运行结果:


列出文件中所有的数据:
Person[name="杜甫", age="45", description="唐朝现实主义诗人"]
Person[name="爱因斯坦", age="20", description="伟大的物理学家,提出相对论理论。"]
Person[name="李白", age="20", description="唐朝浪漫主义诗人"]
Person[name="曹雪芹", age="47", description="《红楼梦》作者"]

在文件中查找关键字 雪,结果如下:
找到结果:Person[name="曹雪芹", age="47", description="《红楼梦》作者"]

posted @ 2011-03-15 20:38  jinmengzhe  阅读(1817)  评论(0编辑  收藏  举报