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

Java I/O 流全景圖:字節/字符、同步/異步、裝飾者模式一網打盡

     編輯:Java 相關知識

前言

Java I/O 是後端開發的基石,卻常被「流太多、易混淆、不知如何選型」所困擾。本文從設計模式、核心抽象、選型決策樹三個維度,構建完整的 I/O 知識體系,附贈高頻場景代碼模板。

一、四大核心抽象基類

抽象類數據單位流向典型子類
InputStream字節 (byte)讀入FileInputStream, ByteArrayInputStream, GZIPInputStream
OutputStream字節 (byte)寫出FileOutputStream, ByteArrayOutputStream, GZIPOutputStream
Reader字符 (char)讀入FileReader, BufferedReader, InputStreamReader
Writer字符 (char)寫出FileWriter, BufferedWriter, OutputStreamWriter

二、字節流 vs 字符流:本質區別與選型鐵律

維度字節流字符流
讀取單位一次讀 1 字節按編碼表讀 1~多字節組成 1 char
適用數據所有二進制:圖片、視頻、音頻、序列化對象純文本:XML、JSON、CSV、日誌、屬性文件
編碼處理無感知,原樣傳輸內建編碼轉換(默認平台編碼,建議顯式指定 UTF-8)
性能無轉換開銷編碼/解碼額外 CPU

選型鐵律:處理純文本 → 字符流(Reader/Writer);其他一切 → 字節流(InputStream/OutputStream)。

三、裝飾者模式:流的靈活組合藝術

Java I/O 大量使用裝飾者模式,通過層層包裝賦予流新能力:

// 經典組合:文件 → 緩衝 → 字符編碼 → 行讀取
BufferedReader reader = new BufferedReader(
    new InputStreamReader(
        new FileInputStream("data.txt"), StandardCharsets.UTF_8
    )
);

// 寫出組合:文件 → 緩衝 → 字符編碼
BufferedWriter writer = new BufferedWriter(
    new OutputStreamWriter(
        new FileOutputStream("out.txt"), StandardCharsets.UTF_8
    )
);

常用裝飾器速查表

裝飾器賦能適用流
BufferedInputStream/OutputStream緩衝,減少系統調用字節流
BufferedReader/Writer緩衝 + readLine()字符流
DataInputStream/OutputStream基本類型序列化字節流
ObjectInputStream/OutputStream對象序列化字節流
GZIPInputStream/OutputStream壓縮/解壓字節流
InputStreamReader/OutputStreamWriter字節⇄字符橋樑(指定編碼)跨層轉換
PrintStream/PrintWriter格式化輸出、不拋異常字節/字符流

四、現代 I/O:NIO.2 與 NIO(非阻塞)

Files API (Java 7+) - 文件操作首選

// 讀取所有行(自動關閉、指定編碼)
List<String> lines = Files.readAllLines(Paths.get("data.txt"), StandardCharsets.UTF_8);

// 大文件流式處理(常數內存)
try (Stream<String> stream = Files.lines(path, StandardCharsets.UTF_8)) {
    stream.filter(s -> s.startsWith("ERROR")).forEach(System.out::println);
}

// 複制/移動/刪除(原子性選項)
Files.copy(src, dest, StandardCopyOption.REPLACE_EXISTING);
Files.move(src, dest, StandardCopyOption.ATOMIC_MOVE);

NIO 非阻塞 I/O (Java 1.4+) - 高併發網絡基石

  • 核心三件套:Channel、Buffer、Selector
  • 單線程管理成千上萬連接(Netty、Tomcat NIO、Jetty 底層皆基於此)
  • 應用層直接使用 Netty 等框架,極少手寫 Selector 循環

五、高頻場景代碼模板

5.1 文本文件讀寫(標準模板)

// 讀取
public List<String> readLines(Path path) throws IOException {
    return Files.readAllLines(path, StandardCharsets.UTF_8);
}

// 寫入(覆蓋模式)
public void writeLines(Path path, Collection<String> lines) throws IOException {
    Files.write(path, lines, StandardCharsets.UTF_8, 
                StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
}

5.2 大文件複製(緩衝流 + try-with-resources)

public void copyLargeFile(Path src, Path dest) throws IOException {
    try (InputStream in = new BufferedInputStream(Files.newInputStream(src));
         OutputStream out = new BufferedOutputStream(Files.newOutputStream(dest))) {
        byte[] buffer = new byte[8192];
        int len;
        while ((len = in.read(buffer)) != -1) {
            out.write(buffer, 0, len);
        }
    }
}

5.3 對象序列化/反序列化

public void serialize(Object obj, Path file) throws IOException {
    try (ObjectOutputStream oos = new ObjectOutputStream(
            new BufferedOutputStream(Files.newOutputStream(file)))) {
        oos.writeObject(obj);
    }
}

public Object deserialize(Path file) throws IOException, ClassNotFoundException {
    try (ObjectInputStream ois = new ObjectInputStream(
            new BufferedInputStream(Files.newInputStream(file)))) {
        return ois.readObject();
    }
}

六、避坑指南

  • ❌ new FileReader(file) → 不指定編碼,跨平台亂碼隱患
    ✅ new InputStreamReader(Files.newInputStream(file), StandardCharsets.UTF_8)
  • ❌ 手動 close() 易漏 → ✅ try-with-resources 自動關閉(Java 7+)
  • ❌ available() 判斷文件大小 → 不可靠(網絡流、壓縮流返回 0)
    ✅ Files.size(path) 或 File.length()
  • ❌ 序列化未聲明 serialVersionUID → 版本升級反序列化失敗
    ✅ 顯式聲明 private static final long serialVersionUID = 1L;

總結

Java I/O 體系雖龐大,核心邏輯清晰:字節流處理二進制,字符流處理文本;裝飾者模式靈活組合能力;NIO.2 Files API 簡化文件操作;NIO 非阻塞支撐高併發網絡。掌握選型決策樹與標準代碼模板,即能應對 95% 的 I/O 開發場景。

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