IO|RandomAccessFile详解、文件任意位置插入数据程序
- 特点
- 构造方法
- 特有方法
- 使用
- 文件任意位置插入程序
特点
RandomAccessFile其实不属于流体系的一员,他主要是封装了字节流的缓冲区,通过内部指针来操作字符数组中的数据。
特点:
- 主要用来 操作文件,构造函数只接收两种类型的参数:通过字符串路径、通过File实例,来创造对象
- 可以对文件进行读操作,也可以对文件进行写操作,在对对象实例化时需要指定操作模式(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();
}
}
}
指定路径的文件是这样的:
在调用randomReader(path, 6);
后运行结果为:
调用randomWriter(path, " world");
后。文件为:
文件任意位置插入程序
用上面的第二种方法如果从不是最后一位开始写数据的话,会覆盖掉原文件的一些内容,如何设计一个程序,使得其可以在文件的任意位置插入内容,并且不破坏原来的文件呢?
思路如下,可以创建出一个临时文件file实例,用seek将指定位置后的数据写入临时文件中,然后将指定内容写入只当文件中,再用seek定位指针,将file中数据写入文件中,最后将临时文件file删除。
这时操作前文件的样子:
我们在逗号和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();
}
}
}
运行结果如图所示: