IO|RandomAccessFile详解、文件任意位置插入数据程序

  • 特点
  • 构造方法
  • 特有方法
  • 使用
  • 文件任意位置插入程序


特点

RandomAccessFile 追加和覆盖 randomaccessfile参数_临时文件


RandomAccessFile其实不属于流体系的一员,他主要是封装了字节流的缓冲区,通过内部指针来操作字符数组中的数据。

特点:

  1. 主要用来 操作文件,构造函数只接收两种类型的参数:通过字符串路径、通过File实例,来创造对象
  2. 可以对文件进行读操作,也可以对文件进行写操作,在对对象实例化时需要指定操作模式(r,rw)

构造方法

public RandomAccessFile(String name, String mode) throws FileNotFoundException {
    this(name != null ? new File(name) : null, mode);
}

public RandomAccessFile(File file, String mode) throws FileNotFoundException {
    this(file, mode, false);
}

model各个参数详解:

  • r 代表以只读方式打开指定文件,如果在此参数下进行写操作,会报异常
  • rw 以读写方式打开指定文件
  • rws 读写方式打开,并对内容或元数据都同步写入底层存储设备
  • rwd 读写方式打开,对文件内容的更新同步更新至底层存储设备

特有方法

public native long getFilePointer() throws IOException;

返回文件记录指针当前的位置,默认情况下都是0号位置

void seek(long pos) throws IOException

设置文件指针到pos位置

之前的IO流,新打开一个流,写操作会覆盖元数据,从元数据的0号位置开始写 ,读操作也是默认从0号位置(起始位置)开始读。seek方法可以改变文件的指针,从指定位置开始读写。

使用

从指定的位置开始,读数据、数据追加操作

public class RandomAccessFileDemo {
    public static void main(String[] args) {
        String path = "C:/Users/Chuuuki/Desktop/test.txt";
        randomReader(path, 6);
        randomWriter(path, " world");
    }

    // 读操作
    public static void randomReader(String path, int pos) {
        try {
            RandomAccessFile accessFile = new RandomAccessFile(path, "r");
            // 获取文件的初始指针
            System.out.println(accessFile.getFilePointer());

            // 将文件指针位置移动到指定位置
            accessFile.seek(pos);

            byte[] bytes = new byte[100];
            int len;
            // 循环读取
            while ((len = accessFile.read(bytes)) != -1) {
                System.out.println(new String(bytes, 0, len));
            }

            accessFile.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 数据追加
    public static void randomWriter(String path, String content) {
        try {
            RandomAccessFile rw = new RandomAccessFile(path, "rw");

            // 文件指针指到末尾
            rw.seek(rw.length());

            rw.write(content.getBytes());

            rw.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

指定路径的文件是这样的:

RandomAccessFile 追加和覆盖 randomaccessfile参数_字符串_02

在调用randomReader(path, 6);后运行结果为:

RandomAccessFile 追加和覆盖 randomaccessfile参数_字符串_03


调用randomWriter(path, " world");后。文件为:

RandomAccessFile 追加和覆盖 randomaccessfile参数_字符串_04

文件任意位置插入程序

用上面的第二种方法如果从不是最后一位开始写数据的话,会覆盖掉原文件的一些内容,如何设计一个程序,使得其可以在文件的任意位置插入内容,并且不破坏原来的文件呢?

思路如下,可以创建出一个临时文件file实例,用seek将指定位置后的数据写入临时文件中,然后将指定内容写入只当文件中,再用seek定位指针,将file中数据写入文件中,最后将临时文件file删除。

这时操作前文件的样子:

RandomAccessFile 追加和覆盖 randomaccessfile参数_临时文件_05


我们在逗号和chuki之间插入“my name is ”

程序如下:

/**
 * 任意位置插入数据
 * @param path
 * @param points        指定的位置
 * @param insertContent 待插入的内容
 */
public static void randomInsert(String path, long points, String insertContent) {
    RandomAccessFile rw = null;
    BufferedReader reader = null;
    BufferedWriter writer = null;
    File temp = null;
    try {
        rw = new RandomAccessFile(path, "rw");
        temp = File.createTempFile("save", "null"); // 创建临时文件
        // prefix -- 前缀字符串定义的文件名;必须至少有三个字符长
        // suffix -- 后缀字符串定义文件的扩展名;如果为null后缀".tmp" 将被使用
        reader = new BufferedReader(new FileReader(temp)); // 临时文件的读取
        writer = new BufferedWriter(new FileWriter(temp)); // 临时文件的写入
        rw.seek(points); // 定位到points,把后面的数据写入临时文件
        byte[] bytes = new byte[100];
        int num = 0;
        while ((num = rw.read(bytes)) != -1) {
            writer.write(new String(bytes, 0, num));
            // 将pos后面的内容写入临时文件
        }
        writer.flush();
        rw.seek(points); // 定位到points,把插入的内容和临时文件写入rw
        rw.write(insertContent.getBytes());

        String amp = null;
        while ((amp = reader.readLine()) != null) {
            rw.write(amp.getBytes());
            // 临时文件已被读取
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            writer.close();
            reader.close();
            rw.close();
            temp.deleteOnExit(); // 关闭流操作和删除临时文件
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

运行结果如图所示:

RandomAccessFile 追加和覆盖 randomaccessfile参数_java_06