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

Java 文件讀寫全攻略:流分類、核心 API、高性能模式與避坑指南

     編輯:Java 相關知識

Java IO 流體系總覽

                    Object
                     ↑
            ┌────────┴────────┐
            │                 │
        InputStream       OutputStream      (字節流,處理二進制:圖片、視頻、音頻)
            │                 │
    ┌───────┴───────┐ ┌─────┴─────┐
    │               │ │           │
FileInputStream  ...  FileOutputStream ...

            │                 │
            ▼                 ▼
        Reader            Writer          (字符流,處理文本:TXT、JSON、CSV、XML)
            │                 │
    ┌───────┴───────┐ ┌─────┴─────┐
    │               │ │           │
FileReader       ...  FileWriter ...

            │                 │
            ▼                 ▼
    BufferedReader    BufferedWriter  (緩衝裝飾器,提升性能,按行讀寫)
            │                 │
            ▼                 ▼
    InputStreamReader OutputStreamWriter (字節↔字符橋梁,指定編碼)

讀文件四大核心模式

1. 字節流讀取 (二進制文件)

public static byte[] readBytes(String path) throws IOException {
    try (FileInputStream fis = new FileInputStream(path);
         ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
        byte[] buffer = new byte[8192];
        int len;
        while ((len = fis.read(buffer)) != -1) {
            baos.write(buffer, 0, len);
        }
        return baos.toByteArray();
    }
}

2. 字符流讀取 (文本文件,指定編碼)

public static String readText(String path, Charset charset) throws IOException {
    try (InputStreamReader isr = new InputStreamReader(
            new FileInputStream(path), charset);
         BufferedReader br = new BufferedReader(isr)) {
        
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null) {
            sb.append(line).append(System.lineSeparator());
        }
        return sb.toString();
    }
}

3. 按行讀取 (最常用,內存友好)

// Java 7+ try-with-resources
public static void processLines(String path, Charset charset, Consumer processor) 
        throws IOException {
    try (BufferedReader br = new BufferedReader(
            new InputStreamReader(new FileInputStream(path), charset))) {
        String line;
        while ((line = br.readLine()) != null) {
            processor.accept(line);
        }
    }
}

// Java 8+ Stream API (自動關閉)
public static List readAllLines(String path, Charset charset) throws IOException {
    try (Stream lines = Files.lines(Paths.get(path), charset)) {
        return lines.collect(Collectors.toList());
    }
}

4. 隨機訪問 (大文件斷點續傳、分片讀取)

public static byte[] readRandom(String path, long offset, int length) throws IOException {
    try (RandomAccessFile raf = new RandomAccessFile(path, "r")) {
        raf.seek(offset);
        byte[] buf = new byte[length];
        int read = raf.read(buf);
        return Arrays.copyOf(buf, read);
    }
}

寫文件核心模式

1. 字節流寫入

public static void writeBytes(String path, byte[] data, boolean append) throws IOException {
    try (FileOutputStream fos = new FileOutputStream(path, append);
         BufferedOutputStream bos = new BufferedOutputStream(fos)) {
        bos.write(data);
    }
}

2. 字符流寫入 (指定編碼)

public static void writeText(String path, String content, Charset charset, boolean append) 
        throws IOException {
    try (OutputStreamWriter osw = new OutputStreamWriter(
            new FileOutputStream(path, append), charset);
         BufferedWriter bw = new BufferedWriter(osw)) {
        bw.write(content);
    }
}

3. 便捷工具類 (Java 7+ NIO.2 Files)

// 一行代碼讀寫 (小文件)
byte[] data = Files.readAllBytes(Paths.get(path));
String text = Files.readString(Paths.get(path), StandardCharsets.UTF_8);
Files.writeString(Paths.get(path), text, StandardCharsets.UTF_8, 
    StandardOpenOption.CREATE, StandardOpenOption.APPEND);
Files.write(Paths.get(path), data, StandardOpenOption.CREATE, StandardOpenOption.APPEND);

// 大文件流式
try (InputStream in = Files.newInputStream(Paths.get(src));
     OutputStream out = Files.newOutputStream(Paths.get(dest), 
         StandardOpenOption.CREATE, StandardOpenOption.APPEND)) {
    in.transferTo(out); // Java 9+ 零拷貝
}

性能對比與選型建議

場景推薦方案緩衝區大小關鍵點
小文本文件 (<10MB)Files.readString/writeString--代碼最簡潔,JDK 內部優化
大文本文件 (行處理)Files.lines() 或 BufferedReader8KB流式處理,不載入全量內存
二進制文件複製Files.copy / in.transferTo(out)--OS 級零拷貝,最快
頻繁追加寫入BufferedWriter + APPEND8KB-64KB減少系統調用
隨機讀寫RandomAccessFile / SeekableByteChannel--支持 seek() 定位
高併發日誌AsyncFileChannel / Log4j2/Logback--異步非阻塞,專業日誌框架

編碼處理鐵律

  1. 顯式指定 Charset:StandardCharsets.UTF_8,永不依賴平台預設編碼
  2. InputStreamReader/OutputStreamWriter 是字節↔字符唯一橋梁
  3. 屬性文件 Properties.load JDK 11+ 支持 UTF-8,舊版需自行轉碼
  4. BOM 頭處理:BOMInputStream (Apache Commons IO) 自動檢測並剝離

資源管理鐵律

// ✅ Java 7+ try-with-resources (自動關閉,異常安全)
try (Resource r = acquire()) { use(r); }

// ✅ Java 8+ Stream 結束自動關閉
try (Stream s = Files.lines(path)) { ... }

// ❌ 手動 close 易漏、異常路徑不關閉
Resource r = acquire();
try { use(r); } finally { if (r != null) r.close(); }

常見坑點避雷

坑點後果解決
未指定編碼讀寫中文亂碼、數據損壞強制 StandardCharsets.UTF_8
大文件 readAllBytesOOM流式分塊處理
循環中創建 FileWriter極慢、文件鎖競爭提取到循環外,用 BufferedWriter
FileReader 無編碼構造器平台相關行為改用 InputStreamReader(fis, UTF_8)
Windows 路徑分隔符硬編碼跨平台失敗Paths.get(...) / File.separator
隨機讀取未檢查 read() 返回值數據截斷循環讀取直到 -1
輸出流未 flush()數據停留緩衝區try-with-resources 自動 flush

現代化替代方案

  • Apache Commons IO:FileUtils.readFileToString、IOUtils.copy、Tailer 尾部監聽
  • Google Guava:Files.asCharSource(path, UTF_8).readLines()、ByteStreams
  • Okio:Okio.buffer(Okio.source(file)).readUtf8()、現代 Kotlin/Java 首選
  • Netty ByteBuf:高性能網絡編程場景

總結

Java 文件讀寫核心在於「字節流處理二進制,字符流處理文本,緩衝流提升性能,編碼顯式指定,資源自動管理」。掌握 Files (NIO.2)、BufferedReader/Writer、InputStreamReader/OutputStreamWriter 三大組合,覆蓋 95% 業務場景。大文件必用流式處理,小文件享受 Files.readString 便利。遵循「零信任編碼、try-with-resources 管理資源、零拷貝傳輸大文件」三大鐵律,構建健壯、高性能、跨平台的文件處理代碼。

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