RandomAccessFile类详解

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

Java食用备忘

第一章 RandomAccessFile类详解



前言

RandomAccessFile 是 Java IO 体系中一个特殊的文件操作类,它区别于普通的流(InputStream/OutputStream、Reader/Writer),核心优势在于支持随机访问文件内容,可自由定位文件读写位置,兼具读和写的功能。


一、核心特性

  • 双向操作能力:同时实现了 DataInput 和 DataOutput 接口,无需分别创建输入流和输出流,可在同一个对象上完成文件的读取与写入操作。
  • 随机访问核心:通过文件指针(file pointer)控制读写位置,文件指针代表当前将要读写的字节偏移量(初始为 0,对应文件开头),支持手动移动指针,实现非顺序的随机读写。
  • 独立于普通流体系:不继承 InputStream 或 OutputStream,是 Java IO 中单独的类,仅用于操作文件,不支持其他 IO 数据源(如网络流)。

二、关键构造方法

RandomAccessFile 的构造方法需指定文件路径 / 文件对象,以及访问模式,核心构造方法如下:

构造方法说明
RandomAccessFile(File file, String mode)以指定 File 对象和访问模式创建实例
RandomAccessFile(String name, String mode)以指定文件路径字符串和访问模式创建实例

核心访问模式(重点)

常用的两种核心模式,决定了文件的操作权限:

  1. “r”:只读模式
    • 仅允许读取文件内容,无法执行写入操作。
    • 如果指定的文件不存在,会抛出 FileNotFoundException。
  2. “rw”:读写模式
    • 允许同时进行文件的读取和写入操作。
    • 如果指定的文件不存在,会自动创建该文件;如果文件已存在,写入操作不会清空原有内容(仅覆盖对应位置的字节)。
    • 补充模式:“rwd”、“rws”(基于 rw 扩展,保证写入数据的持久性,多用于高可靠性场景,日常开发较少使用)。

三、随机访问的核心方法(文件指针控制)

文件指针的移动和定位是 RandomAccessFile 实现随机访问的关键,核心方法如下:

  1. long getFilePointer()
    • 功能:获取当前文件指针的位置(字节偏移量)。
    • 返回值:long 类型,代表当前指针距离文件开头的字节数。
  2. void seek(long pos)
    • 功能:将文件指针移动到指定的绝对位置(核心方法)。
    • 参数 pos:目标字节偏移量(pos >= 0),可以定位到文件任意有效位置(包括文件末尾,用于追加写入)。
  3. int skipBytes(int n)
    • 功能:将文件指针向前(向后不支持)跳过指定的字节数。
    • 返回值:实际跳过的字节数(可能小于 n,如到达文件末尾时)。

四、核心读写方法

由于实现了 DataInput 和 DataOutput 接口,RandomAccessFile 提供了丰富的类型安全读写方法,常用核心方法如下:

1. 读取方法(对应 DataInput 接口)

方法说明
int read()读取单个字节,返回字节值(0-255),到达文件末尾返回 -1
int read(byte[] b)读取字节到数组 b 中,返回实际读取的字节数
byte readByte()读取单个字节(支持负数,范围 -128~127)
int readInt()读取 4 个字节,转换为 int 类型
long readLong()读取 8 个字节,转换为 long 类型
String readUTF()读取 UTF-8 编码的字符串

2. 写入方法(对应 DataOutput 接口)

方法说明
void write(int b)写入单个字节(仅保留低 8 位)
void write(byte[] b)写入字节数组 b 中的所有内容
void writeByte(int b)写入单个字节
void writeInt(int v)写入 4 个字节的 int 类型值
void writeLong(long v)写入 8 个字节的 long 类型值
void writeUTF(String s)写入 UTF-8 编码的字符串

五、典型使用场景

  1. 文件分段读写:如大文件分片上传 / 下载,通过 seek() 定位到分片的起始位置,读取或写入指定大小的字节数据。
  2. 文件内容更新 / 覆盖:无需读取整个文件,直接定位到需要修改的位置,覆盖写入新内容(例如修改配置文件中的某个参数、更新日志文件的指定条目)。
  3. 文件追加写入:先通过 length() 方法获取文件总长度,再用 seek(file.length()) 将指针移到文件末尾,执行写入操作,实现追加效果。
  4. 随机读取文件内容:如读取文件中指定位置的记录(如数据库备份文件、固定格式的日志文件),无需顺序遍历。

六、使用示例(核心功能演示)

示例 1:读写文件 + 指针定位

import java.io.RandomAccessFile;
import java.io.IOException;

public class RandomAccessFileDemo {
    public static void main(String[] args) {
        // 定义文件路径
        String filePath = "test.txt";
        
        try (RandomAccessFile raf = new RandomAccessFile(filePath, "rw")) {
            // 1. 写入数据(初始指针在 0 位置)
            raf.writeUTF("Hello RandomAccessFile");
            raf.writeInt(100);
            raf.writeLong(20260105L);
            
            // 2. 获取当前指针位置
            long currentPos = raf.getFilePointer();
            System.out.println("写入后指针位置:" + currentPos);
            
            // 3. 移动指针到文件开头(pos = 0)
            raf.seek(0);
            
            // 4. 读取数据(按写入顺序读取,类型需对应)
            String str = raf.readUTF();
            int num = raf.readInt();
            long date = raf.readLong();
            
            System.out.println("读取的字符串:" + str);
            System.out.println("读取的int值:" + num);
            System.out.println("读取的long值:" + date);
            
            // 5. 定位到指定位置,覆盖写入
            raf.seek(str.length() + 2); // UTF字符串会先写入2个字节的长度标识,故偏移量需预留
            raf.writeUTF("Java");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

示例 2:文件追加写入

import java.io.RandomAccessFile;
import java.io.IOException;

public class RandomAccessFileAppend {
    public static void main(String[] args) {
        String filePath = "append.txt";
        
        try (RandomAccessFile raf = new RandomAccessFile(filePath, "rw")) {
            // 1. 将指针移到文件末尾
            raf.seek(raf.length());
            
            // 2. 追加写入数据
            raf.writeUTF("这是追加的内容");
            raf.writeByte('\n'); // 换行符
            System.out.println("数据追加成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

七、注意事项

  1. 资源释放:RandomAccessFile 实现了 AutoCloseable 接口,推荐使用 try-with-resources 语法自动关闭资源,避免文件句柄泄露。
  2. 类型匹配:读取数据时,必须与写入时的类型顺序一致(如先写 writeUTF(),后写 writeInt(),读取时需先 readUTF(),后 readInt()),否则会出现数据错乱或 EOFException。
  3. 指针越界:seek() 方法的参数 pos 不能为负数,若超过文件长度,写入时会填充空白字节,读取时会抛出 EOFException。
  4. 编码问题:readUTF() 和 writeUTF() 使用的是 Java 特定的 UTF-8 编码(与标准 UTF-8 略有差异),若读取非该方式写入的字符串,会出现乱码。

总结

  1. RandomAccessFile 核心优势是随机访问(通过 seek() 控制文件指针),兼具读写能力,不依赖普通 IO 流体系。
  2. 核心访问模式:“r”(只读)、“rw”(读写,文件不存在自动创建)。
  3. 关键方法:getFilePointer()(获取指针)、seek()(定位指针)、readXXX()(类型读取)、writeXXX()(类型写入)。
  4. 典型场景:文件分段操作、内容更新、追加写入、随机读取,适合处理固定格式或大文件。

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值