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

Java IO 基石:字節流 InputStream 與 OutputStream 深度解析

     編輯:Java 程式設計入門

IO 體系鳥瞰

Java IO 按數據單位分為字節流(以 byte 為單位,處理圖片、視頻、二進制文件)與字符流(以 char 為單位,處理文本,涉及編碼轉換);按流向分為輸入流(數據進程序)與輸出流(數據出程序)。

四大抽象基類:

  • InputStream — 字節輸入流基類
  • OutputStream — 字節輸出流基類
  • Reader — 字符輸入流基類
  • Writer — 字符輸出流基類

所有具體實現類均以父類名為後綴,如 FileInputStream、BufferedReader。

標準 IO 操作四步驟

  1. 使用 File 定位文件
  2. 選擇具體流子類建立連接
  3. 循環讀/寫數據
  4. 關閉流(釋放文件句柄)

OutputStream — 字節輸出流詳解

核心方法

FileOutputStream 構造方法

// 覆蓋模式
new FileOutputStream(File file)
new FileOutputStream(String name)

// 追加模式(第二參數 true)
new FileOutputStream(File file, boolean append)
new FileOutputStream(String name, boolean append)

實戰示例:高效寫入與追加

public class OutputStreamDemo {
    public static void main(String[] args) throws IOException {
        File file = new File("data.txt");

        // 1. 一次性寫入字節數組(推薦)
        try (OutputStream out = new FileOutputStream(file)) {
            String content = "Hello Java IO";
            out.write(content.getBytes(StandardCharsets.UTF_8));
        }

        // 2. 分塊寫入大數據(避免 OOM)
        try (OutputStream out = new FileOutputStream(file, true)) { // 追加模式
            byte[] buffer = new byte[4096];
            // 模擬分塊寫入
            for (int i = 0; i < 10; i++) {
                String chunk = "Chunk-" + i + "\n";
                out.write(chunk.getBytes());
            }
        }
    }
}

InputStream — 字節輸入流詳解

核心方法

方法說明
abstract void write(int b)寫入單字節(低 8 位)
void write(byte[] b)寫入整個字節數組
void write(byte[] b, int off, int len)寫入數組指定範圍(高性能寫法)
void flush()強制刷新緩衝區到目標
void close()關閉流,隱含 flush

高效讀取模板(避免逐字節讀取性能極差)

public class InputStreamDemo {
    public static void main(String[] args) throws IOException {
        File file = new File("data.txt");

        // 方式一:已知文件較小,一次性讀取
        try (InputStream in = new FileInputStream(file)) {
            byte[] allBytes = in.readAllBytes(); // Java 9+
            System.out.println(new String(allBytes, StandardCharsets.UTF_8));
        }

        // 方式二:通用分塊讀取(推薦,適合任意大小文件)
        try (InputStream in = new FileInputStream(file)) {
            byte[] buffer = new byte[8192]; // 8KB 緩衝區
            int len;
            StringBuilder sb = new StringBuilder();
            while ((len = in.read(buffer)) != -1) {
                sb.append(new String(buffer, 0, len, StandardCharsets.UTF_8));
            }
            System.out.println(sb);
        }

        // 方式三:利用文件長度預分配數組(僅適用小文件)
        try (InputStream in = new FileInputStream(file)) {
            byte[] exact = new byte[(int) file.length()];
            in.readNBytes(exact, 0, exact.length); // Java 11+
            System.out.println(new String(exact, StandardCharsets.UTF_8));
        }
    }
}

常見坑點與最佳實踐

  1. 編碼顯式指定:getBytes(StandardCharsets.UTF_8)、new String(bytes, StandardCharsets.UTF_8),避免平台默認編碼不一致導致亂碼。
  2. try-with-resources:Java 7+ 必須使用,自動關閉流,防止句柄洩漏。
  3. 緩衝區大小:通常 4KB~64KB(如 8192),過大佔堆,過小增加系統調用開銷。
  4. 避免逐字節讀寫:單字節 read()/write(int) 極慢,務必用數組批量操作。
  5. flush() 時機:關鍵數據寫完即 flush;大量寫入可由底層緩衝策略自動處理,最後 close 時自動 flush。

總結

InputStream/OutputStream 是字節流的基石,掌握分塊讀寫模板、編碼顯式化、資源自動關閉三大核心技巧,即可高效處理圖片、視頻、壓縮包等二進制文件。下一篇將講解字符流 Reader/Writer 及轉換流橋接字節與字符。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
方法說明
abstract int read()讀取單字節,返回 0~255,末尾返回 -1
int read(byte[] b)讀取到數組,返回實際讀取字節數,末尾 -1
int read(byte[] b, int off, int len)讀取到數組指定位置
int available()返回可不阻塞讀取的字節估算值
long skip(long n)跳過 n 字節
void close()關閉流