RandomAccessFile
RandomAccessFile是Java输入/输出流体系中的文件内容访问类,它提供了众多的方法来访问文件内容,可以读取也可以写入,与普通的输入/输出流不同的是RandomAccessFile允许自由定义文件记录指针,因此RandomAccessFile支持随机访问的方式,也就是说可以直接跳到文件的任意位置来读写
但是它有一个最大的局限,就是只能读写文件,不能读写其他IO节点
RandomAccessFile提供的方法
RandomAccessFile包含了如下两个方法来操作文件记录指针:
- long getFilePointer(): 返回文件记录指针的当前位置
- void seek(long pos): 将文件记录指针定位到pos的位置
同时RandomAccessFile包含了类似于InputStream的三个read()方法用于读取,也包含了类似于OutputStream的三个write()方法,用于写入,此外RandomAccessFile还包含了一些列的readXxx()和writeXxx()方法来完成输入和输出
RandomAccessFile的构造器
RandomAccessFile有两个构造器,其中一个使用String参数来指定文件名,另一个使用File参数来指定文件本身;此外还有一个mode参数,标识访问模式,该参数有4个值:
- r:以只读的方式打开指定文件
- rw :以读写的方式打开指定文件
- rws :以读写的方式打开指定文件,同时还要对文件的内容或元数据的每个更新都同步写入到底层存储设备
- rwd:以读写的方式打开指定文件,同时还要求对文件内容的每个更新都同步写入到底层存储设备
import java.io.*;
public class RandomAccessFileTest
{
public static void main(String[] args)
{
try (
var raf = new RandomAccessFile("RandomAccessFileTest.java", "r"))
{
// 获取RandomAccessFile对象文件指针的位置,初始位置是0
System.out.println("RandomAccessFile的文件指针的初始位置:"
+ raf.getFilePointer());
// 移动raf的文件记录指针的位置
raf.seek(300);
var bbuf = new byte[1024];
// 用于保存实际读取的字节数
var hasRead = 0;
// 使用循环来重复“取水”过程
while ((hasRead = raf.read(bbuf)) > 0)
{
// 取出“竹筒”中水滴(字节),将字节数组转换成字符串输入!
System.out.print(new String(bbuf, 0, hasRead));
}
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
}
RandomAccessFile依然不能向文件的指定位置插入内容,如果直接插入内容则会把后面的原有内容覆盖,如果要实现向指定位置插入内容,程序需要把插入点后的内容读入缓冲区,插入数据完成后,再将缓冲区的内容追加到文件后面
import java.io.*;
public class AppendContent
{
public static void main(String[] args)
{
try (
//以读、写方式打开一个RandomAccessFile对象
var raf = new RandomAccessFile("out.txt", "rw"))
{
//将记录指针移动到out.txt文件的最后
raf.seek(raf.length());
raf.write("追加的内容!\r\n".getBytes());
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
}
import java.io.*;
public class InsertContent
{
public static void insert(String fileName, long pos,
String insertContent) throws IOException
{
var tmp = File.createTempFile("tmp", null);
tmp.deleteOnExit();
try (
var raf = new RandomAccessFile(fileName, "rw");
// 使用临时文件来保存插入点后的数据
var tmpOut = new FileOutputStream(tmp);
var tmpIn = new FileInputStream(tmp))
{
raf.seek(pos);
// ------下面代码将插入点后的内容读入临时文件中保存------
var bbuf = new byte[64];
// 用于保存实际读取的字节数
var hasRead = 0;
// 使用循环方式读取插入点后的数据
while ((hasRead = raf.read(bbuf)) > 0 )
{
// 将读取的数据写入临时文件
tmpOut.write(bbuf, 0, hasRead);
}
// ----------下面代码插入内容----------
// 把文件记录指针重新定位到pos位置
raf.seek(pos);
// 追加需要插入的内容
raf.write(insertContent.getBytes());
// 追加临时文件中的内容
while ((hasRead = tmpIn.read(bbuf)) > 0)
{
raf.write(bbuf, 0, hasRead);
}
}
}
public static void main(String[] args) throws IOException
{
insert("InsertContent.java", 45, "插入的内容\r\n");
}
}
使用File的createTempFile(String prefix, String suffix)方法创建了一个临时文件,该临时文件会在JVM退出时被删除