参考文献

随机访问文件-RandomAccessFile

img

什么是RandomAccessFile

  • RandomAccessFile 既可以读取文件内容,也可以向文件输出数据.同时,RandomAccessFile 支持“随机访问”的方式,程序快可以直接跳转到文件的任意地方来读写数据.

  • 由于 RandomAccessFile 可以自由访问文件的任意位置,所以如果需要访问文件的部分内容,而不是把文件从头读到尾,使用 RandomAccessFile 将是更好的选择.

  • OutputStream、Writer等输出流不同的是,RandomAccessFile 允许自由定义文件记录指针,RandomAccessFile 可以不从开始的地方开始输出,因此 RandomAccessFile 可以向已存在的文件后追加内容.如果程序需要向已存在的文件后追加内容,则应该使用 RandomAccessFile

RandomAccessFile基础方法

构造方法

1
2
3
RandomAccessFile(File file, String mode)

RandomAccessFile(String name, String mode)
  • **mode :**第二个参数是指以什么模式创建读写流,此参数有固定的输入值,必须为r/rw/rws/rwd其中一个.

    mode 说明
    r 以只读方式打开指定文件.如果尝试对该RandomAccessFile指定的文件执行写入操作,将抛出IOException
    rw 以读取、写入方式打开指定文件.如果文件不存在,则尝试创建文件
    rws 以读取、写入方式打开指定文件.相对于rw模式,还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备.默认情况下(在rw模式下),数据会被缓存,只有当缓存已满或者使用RandomAccessFile.close()关闭流时才会真正写入文件
    rwd rws类似,但仅对文件的内容同步更新到磁盘,而不修改文件的元数据

相关方法

操作文件记录指针
  • long getFilePointer():该方法返回文件记录指针的当前位置,即当前读取/写入操作的位置

    1
    2
    3
    4
    5
    6
    7
    try (RandomAccessFile file = new RandomAccessFile("data.txt", "rw")) {
    // 执行一些操作
    long position = file.getFilePointer(); // 获取当前文件记录指针的位置
    System.out.println("Current position: " + position);
    } catch (IOException e) {
    e.printStackTrace();
    }
  • void seek(long pos):该方法将文件记录指针定位到指定的位置pos

    1
    2
    3
    4
    5
    6
    try (RandomAccessFile file = new RandomAccessFile("data.txt", "rw")) {
    // 执行一些操作
    file.seek(10); // 将文件记录指针定位到位置10
    } catch (IOException e) {
    e.printStackTrace();
    }
  • int skipBytes(int n):

    • 该方法尝试跳过输入的n个字节以丢弃跳过的字节(跳过的字节不读取).
    • 返回实际跳过的字节数.
    • 如果跳过的字节数少于n,可能是由于任意数量的条件引起的,其中一个可能是在跳过n个字节之前已经到达了文件的末尾.
    • 如果n为负数,则不会跳过任何字节.
    1
    2
    3
    4
    5
    6
    try (RandomAccessFile file = new RandomAccessFile("data.txt", "r")) {
    int skippedBytes = file.skipBytes(10); // 跳过10个字节
    System.out.println("Skipped bytes: " + skippedBytes);
    } catch (IOException e) {
    e.printStackTrace();
    }

RandomAccessFile使用示例

指定位置读取文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static void main(String[] args) {
String filePath = "/Users/holelin/file.txt";
try (RandomAccessFile accessFile = new RandomAccessFile(Paths.get(filePath).toFile(), "r")) {
// 获取 RandomAccessFile对象文件指针的位置,初始位置为0
System.out.print("输入内容:" + accessFile.getFilePointer());

// 移动文件记录指针的位置
accessFile.seek(1000);

byte[] b = new byte[1024];
int hasRead = 0;
//循环读取文件
while ((hasRead = accessFile.read(b)) > 0) {
//输出文件读取的内容
System.out.print(new String(b, 0, hasRead));
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}

向文件中追加内容

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) {
String filePath = "/Users/holelin/file.txt";
// 以读写的方式打开一个RandomAccessFile对象
try (RandomAccessFile accessFile = new RandomAccessFile(Paths.get(filePath).toFile(), "rw")) {
//将记录指针移动到该文件的最后
accessFile.seek(accessFile.length());
//向文件末尾追加内容
accessFile.writeChars("这是追加内容。。");
} catch (IOException e) {
e.printStackTrace();
}
}

向文件指定位置插入内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/**
* 向文件指定位置插入内容
*
* @param filePath 源文件路径
* @param pos 插入文件指定位置
* @param writeContent 写入内容
*/
private static void readFileThenWrite(String filePath, long pos, String writeContent) throws IOException {
Path tempPath = Files.createTempFile("tmp", ".part");
try (
// 以读写的方式打开一个RandomAccessFile对象
RandomAccessFile raf = new RandomAccessFile(Paths.get(filePath).toFile(), "rw");
// 创建一个临时文件来保存插入点后的数据
FileOutputStream fileOutputStream = new FileOutputStream(tempPath.toFile());
FileInputStream fileInputStream = new FileInputStream(tempPath.toFile());
) {
// 把文件记录指针定位到pos位置
raf.seek(pos);
raf.seek(pos);

//------------将插入点后的内容读入临时文件中保存------------
byte[] bytes = new byte[64];
//用于保存实际读取的字节数据
int hasRead = 0;
//使用循环读取插入点后的数据
while ((hasRead = raf.read(bytes)) != -1) {
//将读取的内容写入临时文件
fileOutputStream.write(bytes, 0, hasRead);
}

//------------用于插入内容 ------------
//把文件记录指针重新定位到pos位置
raf.seek(pos);

//追加需要插入的内容
raf.write(writeContent.getBytes());

//追加临时文件中的内容
while ((hasRead = fileInputStream.read(bytes)) != -1) {
//将读取的内容写入临时文件
raf.write(bytes, 0, hasRead);
}
}
}}

RandomAccessFile使用场景