ZetCode

Java RandomAccessFile 类

最后修改时间:2025 年 4 月 16 日

java.io.RandomAccessFile 类允许对随机访问文件进行读写操作。与顺序流不同,它支持跳转到文件中的任何位置。这使其对于类似数据库的操作非常有用。

RandomAccessFile 实现了 DataInputDataOutput 接口。它可以读/写基本数据类型和字符串。文件指针可以移动到任何位置以进行随机访问。

RandomAccessFile 类概述

RandomAccessFile 提供了在任何文件位置读写数据的方法。主要功能包括文件指针操作、读/写基本数据类型和文件长度操作。它支持读模式和读写模式。

public class RandomAccessFile implements DataOutput, DataInput, Closeable {
    public RandomAccessFile(String name, String mode);
    public RandomAccessFile(File file, String mode);
    public native long getFilePointer();
    public native void seek(long pos);
    public native long length();
    public native void setLength(long newLength);
    public int read();
    public int read(byte[] b);
    public final int readInt();
    public final void write(int b);
    public final void writeInt(int v);
    public void close();
}

上述代码展示了 RandomAccessFile 提供的关键方法。这些方法允许随机访问读写操作。该类支持字节级和基本数据类型操作。

创建 RandomAccessFile

RandomAccessFile 通过文件路径和访问模式创建。模式可以是 "r" (只读) 或 "rw" (读写)。如果文件不存在,在 "rw" 模式下会创建该文件。

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

public class Main {

    public static void main(String[] args) {
        try {
            // Read-only mode
            RandomAccessFile rafRead = 
                new RandomAccessFile("data.txt", "r");
            
            // Read-write mode (creates file if needed)
            RandomAccessFile rafWrite = 
                new RandomAccessFile("data.txt", "rw");
            
            System.out.println("Read-only file opened");
            System.out.println("Read-write file opened");
            
            rafRead.close();
            rafWrite.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例演示了创建 RandomAccessFile 的不同方式。第一个使用只读模式,而第二个允许读写。完成操作后务必关闭文件以释放资源。在 "rw" 模式下,如果文件不存在,则会自动创建文件。

读写数据

RandomAccessFile 提供了用于读写基本数据类型的方法。这些包括整数、浮点数、双精度数和字符串。文件指针决定了操作发生的位置。

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

public class Main {

    public static void main(String[] args) {
        try (RandomAccessFile raf = 
                new RandomAccessFile("data.dat", "rw")) {
            
            // Write some data
            raf.writeInt(12345);
            raf.writeDouble(678.90);
            raf.writeUTF("Hello World");
            
            // Reset to beginning
            raf.seek(0);
            
            // Read back data
            System.out.println("Int: " + raf.readInt());
            System.out.println("Double: " + raf.readDouble());
            System.out.println("String: " + raf.readUTF());
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例展示了如何使用 RandomAccessFile 读写基本数据类型。数据被顺序写入,然后在跳转到开始位置后读回。writeUTFreadUTF 方法处理带修改的 UTF-8 编码的字符串。

跳转和文件指针

文件指针决定了下一次读/写操作的位置。seek 方法将指针移动到任何位置。getFilePointer 返回当前位置。

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

public class Main {

    public static void main(String[] args) {
        try (RandomAccessFile raf = 
                new RandomAccessFile("seekdemo.dat", "rw")) {
            
            // Write 10 integers (4 bytes each)
            for (int i = 0; i < 10; i++) {
                raf.writeInt(i);
            }
            
            // Jump to 5th integer (position 16)
            raf.seek(16);
            System.out.println("Value at position 16: " + raf.readInt());
            
            // Get current position
            System.out.println("Current position: " + raf.getFilePointer());
            
            // Jump to beginning
            raf.seek(0);
            System.out.println("First value: " + raf.readInt());
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例演示了文件指针操作。整数被写入,然后使用 seek 进行随机访问。每个整数占用 4 个字节,因此第 5 个整数位于位置 16。文件指针在读/写操作期间自动移动。

读写字节

RandomAccessFile 通过 readwrite 方法支持字节级操作。这些方法与字节数组一起用于批量操作。字节操作对于二进制文件处理很有用。

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

public class Main {

    public static void main(String[] args) {
        try (RandomAccessFile raf = 
                new RandomAccessFile("bytes.dat", "rw")) {
            
            // Write some bytes
            byte[] outBytes = {0x01, 0x02, 0x03, 0x04, 0x05};
            raf.write(outBytes);
            
            // Read back bytes
            byte[] inBytes = new byte[5];
            raf.seek(0);
            raf.read(inBytes);
            
            System.out.print("Read bytes: ");
            for (byte b : inBytes) {
                System.out.printf("0x%02X ", b);
            }
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例展示了字节级读/写操作。一个字节数组被写入文件,然后被读回。打印十六进制值以验证数据。字节操作是处理二进制文件格式的基础。

文件长度操作

RandomAccessFile 提供了获取和设置文件长度的方法。length 返回当前大小,而 setLength 可以扩展或截断文件。这些对于管理文件存储非常有用。

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

public class Main {

    public static void main(String[] args) {
        try (RandomAccessFile raf = 
                new RandomAccessFile("lengthdemo.dat", "rw")) {
            
            // Initial length
            System.out.println("Initial length: " + raf.length());
            
            // Extend file
            raf.setLength(100);
            System.out.println("After setLength(100): " + raf.length());
            
            // Write some data
            raf.writeInt(123);
            System.out.println("After writing: " + raf.length());
            
            // Truncate file
            raf.setLength(10);
            System.out.println("After truncation: " + raf.length());
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例演示了文件长度操作。文件被扩展到 100 字节,然后被截断到 10 字节。setLength 既可以增大也可以缩小文件。扩展的区域被填充为零。

将数据追加到文件

要追加数据,请在写入之前跳转到文件末尾。RandomAccessFile 没有像其他流那样的追加模式。必须显式地将文件指针移动到末尾。

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

public class Main {

    public static void main(String[] args) {
        try (RandomAccessFile raf = 
                new RandomAccessFile("appenddemo.txt", "rw")) {
            
            // Write initial data
            raf.writeUTF("Initial line\n");
            
            // Append more data
            raf.seek(raf.length());
            raf.writeUTF("Appended line\n");
            
            // Read entire file
            raf.seek(0);
            byte[] content = new byte[(int) raf.length()];
            raf.readFully(content);
            
            System.out.println(new String(content));
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例展示了如何通过跳转到末尾来追加数据。追加后,文件被完全读回。readFully 确保读取所有请求的字节。这种模式对于日志文件和数据收集很有用。

来源

Java RandomAccessFile 类文档

在本文中,我们涵盖了 Java RandomAccessFile 类的基本方法和功能。理解这些概念对于在 Java 应用程序中使用随机访问文件操作至关重要。

作者

我的名字是 Jan Bodnar,我是一位经验丰富的程序员,在这一领域拥有多年经验。我于 2007 年开始撰写编程文章,此后撰写了 1,400 多篇文章和 8 本电子书。凭借超过八年的教学经验,我致力于分享我的知识并帮助他人掌握编程概念。

列出所有Java教程