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

来源:互联网 发布:plc编程及应用 第4版 编辑:程序博客网 时间:2024/05/16 00:33

                      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);}} 




0 0