在不讀取整個文件到內存的前提下,在文件指定位置插入新內容,並保留原有後續數據。RandomAccessFile 支持隨機讀寫,是實現此需求的理想選擇。
import java.io.*;
public class RandomAccessFileInsert {
/**
* 在文件指定位置插入內容
* @param fileName 文件路徑
* @param pos 插入位置(字節偏移量)
* @param insertContent 要插入的字符串內容
*/
public static void insert(String fileName, long pos, String insertContent) throws IOException {
File tempFile = File.createTempFile("raf_insert_", ".tmp");
tempFile.deleteOnExit(); // JVM 退出時自動刪除
try (RandomAccessFile raf = new RandomAccessFile(fileName, "rw");
FileInputStream fis = new FileInputStream(tempFile);
FileOutputStream fos = new FileOutputStream(tempFile)) {
// 1. 定位到插入位置
raf.seek(pos);
// 2. 將插入位置後的原有內容讀出並寫入臨時文件(備份)
byte[] buffer = new byte[8192]; // 8KB 緩衝區
int len;
while ((len = raf.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
// 3. 回到插入位置,寫入新內容
raf.seek(pos);
byte[] insertBytes = insertContent.getBytes("UTF-8"); // 指定編碼
raf.write(insertBytes);
// 4. 將臨時文件中的備份內容追加寫回原文件
int read;
while ((read = fis.read(buffer)) > 0) {
raf.write(buffer, 0, read);
}
}
}
public static void main(String[] args) {
try {
// 測試:在文件第 57 字節處插入 "插入的內容\r\n"
insert("F:/AttendanceActivity.java", 57, "插入的內容\r\n");
System.out.println("插入完成!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
原文件: [前半部分][插入位置][後半部分]
步驟1: 讀取 [後半部分] -> 臨時文件
步驟2: 寫入 [新內容] -> 原文件插入位置
步驟3: 讀取 臨時文件 -> 追加寫入 原文件
結果: [前半部分][新內容][後半部分]
| 技術點 | 說明 |
|---|---|
RandomAccessFile("rw") | 以讀寫模式打開,支持 seek() 隨機定位 |
seek(pos) | 將文件指針移動到指定字節偏移量 |
| 臨時文件備份 | 避免大文件後半部分佔用過多內存,磁盤換磁盤 |
| 緩衝區大小 8KB | 平衡內存佔用與 I/O 次數,可根據文件大小調整 |
| 編碼一致性 | 讀寫字符串時必須指定編碼(如 UTF-8),否則跨平台亂碼 |
deleteOnExit() | 確保臨時文件最終被清理,避免垃圾文件殘留 |
FileChannel + MappedByteBuffer(大文件高性能)pos=57 表示第 57 個字節。中文 UTF-8 佔 3 字節,需精確計算。try-with-resources 確保所有流正確關閉。File.createTempFile 保證唯一性。RandomAccessFile 配合臨時文件備份,能以常數內存實現文件任意位置插入。掌握 seek()、讀寫分離、編碼處理、資源管理四大要點,即可靈活應對文件隨機修改需求。