首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java IO 進階:RandomAccessFile 隨機讀寫文件詳解

     編輯:Java 程式設計入門

什麼是 RandomAccessFile?

RandomAccessFile 是 Java IO 體系中獨特的存在:它不屬於流體系(不繼承 InputStream/OutputStream),而是直接繼承 Object 並實現 DataInput、DataOutput 接口。其核心優勢在於隨機訪問——可將文件指針移動到任意位置進行讀寫,適合處理固定長度記錄的文件(如數據庫索引、二進制日誌)。

構造方法與模式

構造方法說明
RandomAccessFile(File file, String mode)基於 File 對象
RandomAccessFile(String name, String mode)基於路徑字符串

mode 參數:

  • "r":只讀模式
  • "rw":讀寫模式(最常用)
  • "rws" / "rwd":同步寫入(元數據/數據同步到磁盤)

核心方法速查

方法功能
void seek(long pos)移動文件指針到指定位置(字節偏移量)
long getFilePointer()獲取當前指針位置
long length()獲取文件長度
int skipBytes(int n)跳過 n 個字節,返回實際跳過數
void writeBytes(String s)寫入字符串的低八位(每字符一字節)
void writeInt(int v)寫入 4 字節整數(高位在前)
byte readByte()讀取一個有符號字節
int readInt()讀取 4 字節整數
int read(byte[] b)批量讀取到字節數組
void close()關閉文件,釋放資源

實戰案例:固定長度記錄的存取

假設每條記錄結構:姓名 8 字節(不足補空格)+ 年齡 4 字節 int = 12 字節/條。

public class RandomAccessFileDemo {
    private static final String FILE_PATH = "G:" + File.separator + "JavaTest" + File.separator + "records.dat";
    private static final int RECORD_SIZE = 12; // 8 + 4

    public static void main(String[] args) throws IOException {
        // 1. 寫入三條記錄
        writeRecords();
        // 2. 隨機讀取第 2 條記錄(索引 1)
        readRecord(1);
        // 3. 修改第 1 條記錄的年齡
        updateAge(0, 25);
        // 4. 驗證修改
        readRecord(0);
    }

    static void writeRecords() throws IOException {
        try (RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw")) {
            writeRecord(raf, "liuyan  ", 40);
            writeRecord(raf, "xiaoming", 30);
            writeRecord(raf, "doudou  ", 24);
        }
    }

    static void writeRecord(RandomAccessFile raf, String name, int age) throws IOException {
        raf.writeBytes(name);      // 8 字節
        raf.writeInt(age);         // 4 字節
    }

    static void readRecord(int index) throws IOException {
        try (RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "r")) {
            raf.seek(index * RECORD_SIZE);
            byte[] nameBytes = new byte[8];
            raf.readFully(nameBytes); // 確保讀滿 8 字節
            String name = new String(nameBytes).trim();
            int age = raf.readInt();
            System.out.printf("第 %d 條:姓名=%s,年齡=%d%n", index + 1, name, age);
        }
    }

    static void updateAge(int index, int newAge) throws IOException {
        try (RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw")) {
            raf.seek(index * RECORD_SIZE + 8); // 跳過姓名,定位到年齡
            raf.writeInt(newAge);
            System.out.println("已更新第 " + (index + 1) + " 條記錄年齡為 " + newAge);
        }
    }
}

關鍵注意事項

  1. 固定長度前提:隨機讀寫要求每條記錄長度固定,否則 seek 計算偏移量會出錯。
  2. 字符串處理:writeBytes 只寫低 8 位,中文會截斷。實際項目建議使用 writeChar(2 字節/字符)或預先編碼為定長字節數組(如 UTF-8 定長填充)。
  3. readFully vs read:read(byte[]) 可能讀不滿數組,關鍵數據務必用 readFully 保證讀滿。
  4. 線程安全:RandomAccessFile 非線程安全,多線程環境需自行加鎖或使用 NIO FileChannel。
  5. 關閉資源:務必在 finally 或 try-with-resources 中調用 close(),否則文件鎖可能不釋放。

對比總結

特性RandomAccessFileFileInputStream/FileOutputStreamNIO FileChannel
隨機訪問✅ 原生支持❌ 僅順序✅ position()
讀寫模式單對象雙向分離雙流Channel 雙向
線程安全❌❌✅ (配合鎖)
性能(大文件)中等較低高 (零拷貝)
適用場景固定長度記錄、小型嵌入式數據庫流式讀寫高性能、大文件、網絡傳輸
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved