Saul's blog Saul's blog
首页
后端
分布式
前端
更多
分类
标签
归档
友情链接
关于
GitHub (opens new window)

Saul.J.Wu

立身之本,不在高低。
首页
后端
分布式
前端
更多
分类
标签
归档
友情链接
关于
GitHub (opens new window)
  • Java入门基础

  • Java核心基础

    • 多线程

    • Java常用类

    • 枚举类与注解

    • Java集合

    • 数据结构与算法

    • 泛型

    • IO流

      • IO流概述
      • File对象
      • InputStream
      • OutputStream
      • Filter模式
      • 操作Zip
      • 读取classpath资源
      • 序列化
      • Reader
      • Writer
      • 转换流
      • PrintStream和PrintWriter
      • RandomAccessFile
        • 概述
        • 记录指针
        • 构造器
        • 模拟插入
        • 使用场景
        • 小结
      • Files工具类
    • 网络编程

    • 反射

    • 函数式编程

  • 设计模式

  • Web开发

  • SpringBoot

  • 微服务

  • Elasticsearch

  • 运维

  • 后端
  • Java核心基础
  • IO流
SaulJWu
2021-01-09

RandomAccessFile

# 概述

RandomAccessFile 声明在java.io包下,但直接继承于java.lang.Object类。并且它实现了DataInput、DataOutput这两个接口,也就意味着这个类既可以读也可以写。

RandomAccessFile 类支持“随机访问” 的方式,程序可以直接跳到文件的任意地方来读、写文件

  • 支持只访问文件的部分内容
  • 可以向已存在的文件后追加内容

# 记录指针

RandomAccessFile 对象包含一个记录指针,用以标示当前读写处的位置。

RandomAccessFile类对象可以自由移动记录指针:

  • long getFilePointer():获取文件记录指针的当前位置
  • void seek(long pos):将文件记录指针定位到pos位置

# 构造器

  • public RandomAccessFile(File file, String mode)
  • public RandomAccessFile(String name, String mode)

创建RandomAccessFile类实例需要指定一个mode 参数

该参数指定RandomAccessFile的访问模式:

  • r: 以只读方式打开
  • rw:打开以便读取和写入
  • rwd:打开以便读取和写入;同步文件内容的更新
  • rws:打开以便读取和写入;同步文件内容和元数据的更新

如果模式为只读r。则不会创建文件,而是会去读取一个已经存在的文件,如果读取的文件不存在则会出现异常。

如果模式为rw读写。如果文件不存在则会去创建文件,如果存在则不会创建。(默认情况下,从头覆盖)

# 模拟插入

如果我要去读写文件,自带的方法只能是覆盖,如果需求是在某个位置插入文字内容,应该怎么实现?

1.在插入前,记录插入位置后面的全部内容,存起来。

2.插入文件内容,记录当前指针。

3.把存起来的内容,从记录指针位置重新写入。

@Test
public void test() trhows IOException{
    try(RandomAccessFile raf = new RandomAccessFile("hello.txt","rw")){
        //1.在插入前,记录插入位置后面的全部内容,存起来。假设是第4个位置
        raf.seek(3);
        StringBuilder builder = new StringBuilder((int)new File("hello.txt").length());
        bute[] buffer = new byte[20];
        while((int len = raf.read(buufer)) != -1){
            builder.append(new String(buffer,0,len));
        }
        //2.因为读取了文件,此时指针已经到达文件的末尾,所以要回到我想要插入的位置,插入文件内容
        raf.seek(3);
        raf.write("test".getBytes());
        //3.把存起来的内容,从记录指针位置重新写入。
        raf.write(builder.toString().getBytes());
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

此时已经实现了插入数据效果。

很显然,使用RndomAccessFile插入数据非常消耗内存,因为得把后面的数据事先缓存起来,如果文件小还好,如果文件大一些的话,就不实用了。

所以如果想要插入数据,可以将StringBuilder替换为ByteArrayOutputStream,这个流有点类似于StringBuilder,内置了数组,所以它比较方便插入数据,这里就不展开说了。

# 使用场景

我们可以用RandomAccessFile这个类,来实现一个多线程断点下载的功能,用过下载工具的朋友们都知道,下载前都会建立两个临时文件,一个是与被下载文件大小相同的空文件,另一个是记录文件指针的位置文件,每次暂停的时候,都会保存上一次的指针,然后断点下载的时候,会继续从上一次的地方下载,从而实现断点下载或上传的功能,有兴趣的朋友们可以自己实现下。

# 小结

  • RandomAccessFile可以作为输入流,又可以作为输出流。
  • RandomAccessFile可以对文件内容覆盖
  • RandomAccessFile有一个非常好的方法seek(long pos),可以深入到文件某个位置
帮我改善此页面 (opens new window)
#RandomAccessFile#断点
上次更新: 2021/01/10, 04:14:07
PrintStream和PrintWriter
Files工具类

← PrintStream和PrintWriter Files工具类→

最近更新
01
zabbix学习笔记二
02-28
02
zabbix学习笔记一
02-10
03
Linux访问不了github
12-08
更多文章>
Theme by Vdoing | Copyright © 2020-2022 Saul.J.Wu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式