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

Java IO 進階:RandomAccessFile 隨機存取檔案完整指南

     編輯:Java 相關知識

RandomAccessFile 核心特性

RandomAccessFile 是 Java IO 體系中獨特的存在——它同時支援檔案的讀取與寫入,且能夠隨機定位至任意位置進行操作。不同於 FileInputStream(僅讀)與 FileOutputStream(僅寫)的單向流設計,RandomAccessFile 實作了 DataInput 與 DataOutput 介面,提供豐富的基本型別讀寫方法。

四種開啟模式深度解析

模式說明同步策略
"r"唯讀模式,嘗試寫入會拋出 IOException—
"rw"讀寫模式,標準操作關閉檔案時同步內容至儲存裝置
"rws"讀寫 + 內容與中繼資料即時同步每次內容或中繼資料更新皆同步寫入底層儲存
"rwd"讀寫 + 僅內容即時同步每次內容更新同步寫入,中繼資料不強制同步

中繼資料與同步機制的關鍵差異

所謂「中繼資料」包含檔案大小、建立時間、修改時間、擁有者、權限等資訊。"rws" 強制同步中繼資料,確保檔案系統結構立即持久化;"rwd" 僅同步檔案內容,效能略優於 "rws";"rw" 則依賴作業系統快取策略,關閉時才保證落盤。

核心 API 快速查閱

// 建構子
RandomAccessFile(File file, String mode)
RandomAccessFile(String fileName, String mode)

// 定位與長度
void seek(long offset)          // 移動檔案指標
long getFilePointer()           // 取得目前指標位置
long length()                   // 取得檔案長度
void setLength(long newLength)  // 設定檔案長度(可截斷或擴充)

// 基本型別讀取
int read() / read(byte[] b) / read(byte[] b, int off, int len)
final boolean readBoolean()
final byte readByte()
final char readChar()
final double readDouble()
final float readFloat()
final int readInt()
final long readLong()
final short readShort()
final String readUTF()

// 基本型別寫入
void write(int b) / write(byte[] b) / write(byte[] b, int off, int len)
final void writeBoolean(boolean v)
final void writeByte(int v)
final void writeChar(int v)
final void writeDouble(double v)
final void writeFloat(float v)
final void writeInt(int v)
final void writeLong(long v)
final void writeShort(int v)
final void writeUTF(String str)

// 通道操作
final FileChannel getChannel()  // 取得 FileChannel,支援 NIO 操作

實戰範例:隨機讀寫與指標控制

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.charset.StandardCharsets;

public class RandomAccessFileDemo {
    private static final String FILE_PATH = "random_access_demo.txt";

    public static void main(String[] args) {
        try {
            demoBasicReadWrite();
            demoRandomAccess();
            demoFileChannel();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 基本讀寫:寫入字串、基本型別,再讀回驗證
    private static void demoBasicReadWrite() throws IOException {
        try (RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw")) {
            // 寫入 UTF-8 字串(含長度前綴)
            raf.writeUTF("Hello RandomAccessFile");
            raf.writeInt(2024);
            raf.writeDouble(Math.PI);
            raf.writeBoolean(true);

            // 重置指標讀取
            raf.seek(0);
            System.out.println("字串: " + raf.readUTF());
            System.out.println("整數: " + raf.readInt());
            System.out.println("浮點: " + raf.readDouble());
            System.out.println("布林: " + raf.readBoolean());
        }
    }

    // 隨機存取:修改檔案中間資料、截斷、擴充
    private static void demoRandomAccess() throws IOException {
        try (RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw")) {
            long originalLen = raf.length();
            System.out.println("原始長度: " + originalLen);

            // 移至中間覆寫 4 位元組
            raf.seek(originalLen / 2);
            raf.writeInt(0xCAFEBABE);

            // 擴充檔案至 1KB,新增區域填 0
            raf.setLength(1024);
            System.out.println("擴充後長度: " + raf.length());

            // 截斷至 100 位元組
            raf.setLength(100);
            System.out.println("截斷後長度: " + raf.length());
        }
    }

    // 搭配 FileChannel 進行高效 NIO 操作
    private static void demoFileChannel() throws IOException {
        try (RandomAccessFile raf = new RandomAccessFile(FILE_PATH, "rw")) {
            var channel = raf.getChannel();
            var buffer = java.nio.ByteBuffer.allocate(64);
            buffer.put("NIO Channel Write".getBytes(StandardCharsets.UTF_8));
            buffer.flip();
            channel.write(buffer);
            System.out.println("Channel 寫入完成,檔案大小: " + channel.size());
        }
    }
}

效能考量與最佳實踐

  • 大檔案隨機讀寫:RandomAccessFile 適合需頻繁跳躍位置的場景(如資料庫索引、日誌分析),避免全檔讀入記憶體。
  • 同步模式選擇:關鍵資料建議用 "rwd" 平衡效能與持久化保證;金融交易等強一致性需求可用 "rws"。
  • NIO 整合:透過 getChannel() 結合 MappedByteBuffer 可實現記憶體映射檔案,進一步提升大檔案處理效能。
  • 編碼處理:writeUTF/readUTF 使用修改版 UTF-8(含長度前綴),跨平台交互時需注意相容性;一般文字建議自行指定 StandardCharsets.UTF_8。

常見陷阱提醒

  1. 非執行緒安全:多執行緒並發操作同一 RandomAccessFile 實例需自行同步。
  2. 指標越界:seek() 允許定位至檔案末尾之後,後續寫入會隱性擴充檔案(中間補 0),讀取則回傳 -1。
  3. 資源洩漏:務必使用 try-with-resources 或 finally 區塊確保 close() 被呼叫,釋放檔案鎖定。

掌握 RandomAccessFile 的隨機存取與同步機制,能為 Java 檔案處理帶來靈活且高效的解決方案,特別適用於結構化資料儲存與大檔案隨機訪問場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved