通过前面的学习我们知道,如果准备读文件,需要建立指向该文件的输入流;如果准备写文件,需要建立指向该文件的输出流。那么,能否建立一个流,通过该流既能读文件也能写文件呢?这正是本节要介绍的随机流。


RandomAccessFile类创建的流称做随机流,与前面的输入、输出流不同的是,RandomAccessFile类既不是InputStream类的子类,也不是OutputStream类的子类。但是RandomAccessFile类创建的流的指向既可以作为流的源,也可以作为流的目的地,换句话说,当准备对一个文件进行读写操作时,创建一个指向该文件的随机流即可,这样既可以从这个流中读取文件中的数据,也可以通过这个流写入数据到文件。


以下是RandomAccessFile类的两个构造方法:

1)RandomAccessFile(String name,String mode)

参数name用来确定一个文件名,给出创建的流的源,也是流目的地。参数mode取r(只读)或rw(可读写),决定创建的流对文件的访问权利。

2)RandomAccessFile(File file,String mode)

参数file是一个File对象,给出创建的流的源,也是流目的地。参数mode取r(只读)或rw(可读写),决定创建的流对文件的访问权利。


注意:RandomAccessFile流指向文件时,不刷新文件。


RandomAccessFile类中有一个方法seek(long a)用来定位RandomAccessFile流的读写位置,其中参数a确定读写位置距离文件开头的字节个数。另外流还可以调用getFilePointer()方法获取流的当前读写位置。RandomAccessFile流对文件的读写比顺序读写更为灵活。


例如,把几个int型整数写入到一个名字为tom.dat文件中,然后按相反顺序读出这些数据:

import java.io.*;
public class Main {
    public static void main(String args[]) {
        RandomAccessFile inAndOut = null;
        int data[] = {1,2,3,4,5,6,7,8,9,10};
        try {
            inAndOut = new RandomAccessFile("tom.dat","rw");
            for(int i=0;i<data.length;i++) {
                inAndOut.writeInt(data[i]);
            }
            for(long i = data.length-1;i>=0;i--) {
                inAndOut.seek(i*4);
                System.out.printf("\t%d",inAndOut.readInt());
                /*
                一个int型数据占4个字节,inAndOut从文件的第36个字节读取最后面的一个整数,每隔4个字节往前读取一个整数
                */
            }
            inAndOut.close();
        }
        catch(IOException e) {}
    }
}


RandomAccessFile流的常用方法如下:

方法说明
close()关闭文件
getFilePointer()获取当前读写的位置
length()获取文件的长度
read()从文件中读取一个字节的数据
readBoolean()从文件中读取一个布尔值,0代表false;其他值代表true
readByte()

从文件中读取一个字节

readChar()从文件中读取一个字符(2个字节)
readDouble()从文件中读取一个双精度浮点值(8 个字节)
readFloat()从文件中读取一个单精度浮点值(4个字节)
readFully(byte b[])读b.length字节放入数组b,完全填满该数组
readInt()从文件中读取一个int值(4个字节)
readLine()从文件中读取一个文本行
readLong()从文件中读取一个长型值(8个字节)
readShort()从文件中读取一个短型值(2个字节)
readUnsignedByte()从文件中读取一个无符号字节(1个字节)
readUnsignedShort()从文件中读取一个无符号短型值(2个字节)
readUTF()从文件中读取一个UTF字符串
seek(long position)定位读写位置
setLength(long newlength)设置文件的长度
skipBytes(int n)在文件中跳过给定数量的字节
write(byte b[])写b.length个字节到文件
writeBoolean(boolean v)把一个布尔值作为单字节值写入文件
writeByte(int v)向文件写入一个字节
writeBytes(String s)向文件写入一个字符串
writeChar(char c)向文件写入一个字符
writeChars(String s)向文件写入一个作为字符数据的字符串
writeDouble(double v)向文件写入一个双精度浮点值
writeFloat(float v)向文件写入一个单精度浮点值
writeInt(int v)向文件写入一个int值
writeLong(long v)向文件写入一个长型int值
writeShort(int v)向文件写入一个短型int值
writeUTF(String s)写入一个UTF字符串


注意:RandomAccessFile流的readLine()方法在读取含有非ASCⅡ字符的文件时,比如含有汉字的文件,会出现“乱码”现象。因此,需要把readLine()读取的字符串用“iso-8859-1”编码重新编码存放到byte数组中,然后再用当前机器的默认编码将该数组转化为字符串,操作如下:

1.读取

String str = in.readLine();

2.用“iso-8859-1”重新编码

byte b[] = str.getBytes("iso-8859-1");

3.使用当前机器的默认编码将字节数组转化为字符串

String content = new String(b);

如果机器的默认编码是“GB2312”,那么

String content = new String(b);

等同于

String content = new String(b,"GB2312");


例如:

import java.io.*;
public class Main {
    public static void main(String args[]) {
        RandomAccessFile in = null;
        try {
            in = new RandomAccessFile("Main.java","rw");
            long length = in.length(); //获取文件的长度
            long position = 0;
            in.seek(position); //将读取位置定位到文件的起始
            while(position<length) {
                String str = in.readLine();
                byte b[] = str.getBytes("iso-8859-1");
                str = new String(b);
                position = in.getFilePointer();
                System.out.println(str);
            }
        }
        catch(IOException e) {}
    }
}


点赞(0)

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

Dotcpp在线编译      (登录可减少运行等待时间)