随机读取文件--RandomAccessFile的应用实例

本文介绍了Java中RandomAccessFile的使用,通过实例展示了如何将员工信息写入文件并反向读取。RandomAccessFile提供了一种在文件中随机定位和读写的能力,它不是InputStream或OutputStream的子类,而是直接实现了DataInput和DataOutput接口。通过使用seek()和getFilePointer()等方法,可以实现对文件内容的灵活操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

                      RandomAccessFile是用来访问那些保存数据记录的文件的,这样你就可以用seek( )方法来访问记录,并进行读写了。这些记录的大小不必相同;但是其大小和位置必须是可知的。RandomAccessFile竟然会是不属于InputStream和OutputStream类系的。实际上,除了实现DataInput和DataOutput接口之外(DataInputStream和DataOutputStream也实现了这两个接口),它和这两个类系毫不相干,甚至都没有用InputStream和OutputStream已经准备好的功能;它是一个完全独立的类,所有方法(绝大多数都只属于它自己)都是从零开始写的。这可能是因为RandomAccessFile能在文件里面前后移动,所以它的行为与其它的I/O类有些根本性的不同。总而言之,它是一个直接继承Object的,独立的类。基本上,RandomAccessFile的工作方式是,把DataInputStream和DataOutputStream粘起来,再加上它自己的一些方法,比如定位用的getFilePointer( ),在文件里移动用的seek( ),以及判断文件大小的length( )。此外,它的构造函数还要一个表示以只读方式("r"),还是以读写方式("rw")打开文件的参数 (和C的fopen( )一模一样)。它不支持只写文件,从这一点上看,假如RandomAccessFile继承了DataInputStream,它也许会干得更好。只有RandomAccessFile才有seek方法,而这个方法也只适用于文件。BufferedInputStream有一个mark( )方法,你可以用它来设定标记(把结果保存在一个内部变量里),然后再调用reset( )返回这个位置,但是它的功能太弱了,而且也不怎么实用。
                下面的实例实现了把员工信息写入本地文件,然后逆序读取的功能.

1.员工类

<pre name="code" class="java">
 * 流与文件:本程序以一个员工记录表演示了RandomAccessFile随机读取
 * (原文参考:《Java核心技术》第九版) 
 * @author lijtaos 
 * @version 1.0 2015-04-12 
 * @Email lijtaos@sina.com 
 * 
 */   
/*这是一个员工类*/  
import java.util.*;
public class Employee
{
   //姓名的长度:40字符=80字节
   public static final int NAME_SIZE = 40;
   //每条记录的长度
   public static final int RECORD_SIZE = 2 * NAME_SIZE + 8 + 4 + 4 + 4;
   
   private String name;
   private double salary;
   private Date hireDay;

   public Employee() {}

   public Employee(String n, double s, int year, int month, int day)
   {  
      name = n;
      salary = s;
      GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);
      hireDay = calendar.getTime();
   }

   public String getName()
   {
      return name;
   }

   public double getSalary()
   {
      return salary;
   }

   public Date getHireDay()
   {  
      return hireDay;
   }

   /**
      Raises the salary of this employee.
      @byPercent the percentage of the raise
   */
   public void raiseSalary(double byPercent)
   {  
      double raise = salary * byPercent / 100;
      salary += raise;
   }

   public String toString()
   {  
      return getClass().getName()
         + "[name=" + name
         + ",salary=" + salary
         + ",hireDay=" + hireDay
         + "]";
   }
}


2.数据读写类


/** 
 * 流与文件:本程序以一个员工记录表演示了RandomAccessFile随机读取
 * (原文参考:《Java核心技术》第九版) 
 * @author lijtaos 
 * @version 1.0 2015-04-12 
 * @Email lijtaos@sina.com 
 * 
 */ 
//对数据进行读写的工具类
import java.io.*;
public class DataIO
{
   //读取指定长度的数据
   public static String readFixedString(int size, DataInput in) 
      throws IOException
   {  
      StringBuilder b = new StringBuilder(size);
      int i = 0;
      boolean more = true;
      while (more && i < size)
      {  
         char ch = in.readChar();
         i++;
         if (ch == 0) 
			more = false;
         else 
			b.append(ch);
      }
      in.skipBytes(2 * (size - i));
      return b.toString();
   }
	//写入指定长度的数据
   public static void writeFixedString(String s, int size, DataOutput out) 
      throws IOException
   {
      for (int i = 0; i < size; i++)
      {  
         char ch = 0;
         if (i < s.length()) 
			ch = s.charAt(i);
         out.writeChar(ch);
      }
   }
}

3.测试类


/** 
 * 流与文件:本程序以一个员工记录表演示了RandomAccessFile随机读取
 * (原文参考:《Java核心技术》第九版) 
 * @author lijtaos 
 * @version 1.0 2015-04-12 
 * @Email lijtaos@sina.com 
 * 
 */ 
/*
	将三条员工记录写入文件中,然后逆序读出。
*/
import java.io.*;
import java.util.*;
public class RandomAccessEmployee
{
	public static void main(String[] args) 
		throws IOException
	{
		//员工对象数组
		Employee[] emps=new Employee[3];
		emps[0]=new Employee("石凉",9000.00,2015,12,23);
		emps[1]=new Employee("赵忠祥",8000.00,2013,11,24);
		emps[2]=new Employee("罗京",7000.00,2012,10,25);
		//写数据
		DataOutputStream out=
			new DataOutputStream(new FileOutputStream("emp.dat"));
		
			for(Employee e : emps)
				writeData(out,e);
		out.close();
		//读数据
		RandomAccessFile in=new RandomAccessFile("emp.dat","r");
			//计算文件中包含的员工数
			int n=(int)(in.length()/Employee.RECORD_SIZE);
			Employee[] newEmps=new Employee[n];
			//逆序读取员工记录
			for(int i=n-1;i>=0;i--)
			{
				newEmps[i]=new Employee();
				//把指针跳到文件中该员工的记录头部
				in.seek(i*Employee.RECORD_SIZE);
				newEmps[i]=readData(in);
			} 
				//打印读取的员工记录
			for(Employee e : newEmps)
				System.out.println(e);
			
			in.close();
		}
	/**
	*把员工数据写入输出流
	*@param out 数据输出流
	*@param e 员工对象
	**/
	public static void writeData(DataOutput out,Employee e)
		throws IOException
	{
		DataIO.writeFixedString(e.getName(),Employee.NAME_SIZE,out);
		out.writeDouble(e.getSalary());
		//Gregorian calendar 公历 ; 格里历 ; 格列高利历 ; 阳历
		GregorianCalendar calendar=new GregorianCalendar();
		calendar.setTime(e.getHireDay());
		out.writeInt(calendar.get(Calendar.YEAR));
		out.writeInt(calendar.get(Calendar.MONTH)+1);
		out.writeInt(calendar.get(Calendar.DAY_OF_MONTH));
	}
	/**
	从输入流中读取员工数据
	@param in 数据输入流
	@return 员工对象
	*/
	public static Employee readData(DataInput in)
		throws IOException
	{
		String name=DataIO.readFixedString(Employee.NAME_SIZE,in);
		double salary=in.readDouble();
		int y=in.readInt();
		int m=in.readInt();
		int d=in.readInt();
		return new Employee(name,salary,y,m-1,d);
	}
} 




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值