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

Java IO 流完全指南:字節流與字符流核心 API、緩衝策略與實戰模式

     編輯:Java 相關知識

前言

Java IO 流是處理數據輸入輸出的核心機制,分為字節流 (處理二進制數據) 和字符流 (處理文本數據)。本文系統梳理四大抽象基類、核心實現類、裝飾器模式應用、緩衝策略、NIO.2 現代 API 及實戰工具類封裝。

IO 流體系總覽

1. 四大抽象基類

類別方向數據類型典型實現
InputStream輸入字節 (byte)FileInputStream, ByteArrayInputStream
OutputStream輸出字節 (byte)FileOutputStream, ByteArrayOutputStream
Reader輸入字符 (char)FileReader, StringReader
Writer輸出字符 (char)FileWriter, StringWriter

2. 轉換橋樑

// 字節流 → 字符流 (指定編碼)
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"), "UTF-8");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt"), "UTF-8");

// 緩衝增強
BufferedReader br = new BufferedReader(isr);
BufferedWriter bw = new BufferedWriter(osw);

核心實現類詳解

1. 文件操作基礎

// 字節流寫入
try (FileOutputStream fos = new FileOutputStream("data.bin")) {
    fos.write("Hello".getBytes(StandardCharsets.UTF_8));
    fos.flush(); // 強制刷新緩衝區
}

// 字符流寫入 (自動處理編碼)
try (FileWriter fw = new FileWriter("text.txt")) {
    fw.write("Hello World");
    fw.write('\n');
    fw.write(new char[]{'J', 'a', 'v', 'a'});
}

// 字符流讀取
try (FileReader fr = new FileReader("text.txt")) {
    char[] buffer = new char[1024];
    int len;
    while ((len = fr.read(buffer)) != -1) {
        System.out.print(new String(buffer, 0, len));
    }
}

2. 緩衝流:效能關鍵

// 緩衝讀取:按行讀取、減少系統調用
try (BufferedReader br = new BufferedReader(new FileReader("large.txt"))) {
    String line;
    while ((line = br.readLine()) != null) {
        process(line);
    }
}

// 緩衝寫入:批量刷新
try (BufferedWriter bw = new BufferedWriter(new FileWriter("out.txt"))) {
    for (int i = 0; i < 10000; i++) {
        bw.write("Line " + i);
        bw.newLine(); // 跨平台換行符
    }
    // bw.flush(); // 手動刷新,close() 會自動調用
}

3. 內存流:高速臨時存儲

// 字節陣列流:內存讀寫
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (DataOutputStream dos = new DataOutputStream(baos)) {
    dos.writeInt(123);
    dos.writeUTF("Hello");
}
byte[] data = baos.toByteArray();

// 字符串讀寫
StringWriter sw = new StringWriter();
try (PrintWriter pw = new PrintWriter(sw)) {
    pw.println("Line 1");
    pw.printf("Value: %d%n", 42);
}
String content = sw.toString();

4. 數據流:基本類型序列化

try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.dat"))) {
    dos.writeBoolean(true);
    dos.writeInt(100);
    dos.writeDouble(3.14);
    dos.writeUTF("中文");
}

try (DataInputStream dis = new DataInputStream(new FileInputStream("data.dat"))) {
    boolean b = dis.readBoolean();
    int i = dis.readInt();
    double d = dis.readDouble();
    String s = dis.readUTF(); // 修改版 UTF-8
}

5. 物件流:對象序列化

// 要求實現 Serializable
public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private transient String password; // 不序列化
    // ...
}

// 序列化
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.dat"))) {
    oos.writeObject(new User("Alice", "secret"));
}

// 反序列化
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.dat"))) {
    User user = (User) ois.readObject();
}

裝飾器模式在 IO 中的應用

Java IO 經典應用裝飾器模式,動態組合功能:

// 核心:FileInputStream (基本功能)
InputStream is = new FileInputStream("file.txt");

// 層層包裝:緩衝 → 轉換字符 → 按行讀取
Reader reader = new BufferedReader(
    new InputStreamReader(
        new BufferedInputStream(  // 可選:雙層緩衝
            new FileInputStream("file.txt")), 
        StandardCharsets.UTF_8));

裝飾器鏈圖解

FileInputStream (節點流)
    ↓ 包裝
BufferedInputStream (緩衝)
    ↓ 包裝
InputStreamReader (字節→字符轉換)
    ↓ 包裝
BufferedReader (字符緩衝 + readLine)
    ↓ 使用
readLine() / read(char[])

實戰工具類封裝

1. 通用文件讀寫工具

public final class IoUtils {
    private IoUtils() {}

    /** 讀取文件為字符串 (UTF-8) */
    public static String readString(Path path) throws IOException {
        return Files.readString(path, StandardCharsets.UTF_8);
    }

    /** 讀取文件為字節陣列 */
    public static byte[] readBytes(Path path) throws IOException {
        return Files.readAllBytes(path);
    }

    /** 讀取文件所有行 */
    public static List<String> readLines(Path path) throws IOException {
        return Files.readAllLines(path, StandardCharsets.UTF_8);
    }

    /** 寫入字符串到文件 */
    public static void writeString(Path path, String content) throws IOException {
        Files.writeString(path, content, StandardCharsets.UTF_8, 
            StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
    }

    /** 寫入字節陣列 */
    public static void writeBytes(Path path, byte[] data) throws IOException {
        Files.write(path, data, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
    }

    /** 追加寫入 */
    public static void appendString(Path path, String content) throws IOException {
        Files.writeString(path, content, StandardCharsets.UTF_8,
            StandardOpenOption.CREATE, StandardOpenOption.APPEND);
    }

    /** 大文件複製 (NIO.2 零拷貝) */
    public static long copyLarge(Path src, Path dest) throws IOException {
        return Files.copy(src, dest, StandardCopyOption.REPLACE_EXISTING);
    }
}

2. 緩衝複製大文件 (傳統 IO)

public static void copyLargeFile(File src, File dest) throws IOException {
    try (FileInputStream fis = new FileInputStream(src);
         FileOutputStream fos = new FileOutputStream(dest);
         FileChannel inChannel = fis.getChannel();
         FileChannel outChannel = fos.getChannel()) {
        
        // NIO Channel 零拷貝 (內核態直接傳輸)
        long transferred = 0;
        long size = inChannel.size();
        while (transferred < size) {
            transferred += inChannel.transferTo(transferred, size - transferred, outChannel);
        }
    }
}

NIO.2 現代文件 API (Java 7+)

1. Path 與 Files 核心類

Path path = Paths.get("data", "user.txt"); // 跨平台路徑

// 常用操作
Files.exists(path);
Files.isDirectory(path);
Files.size(path);
Files.deleteIfExists(path);
Files.createDirectories(path.getParent());
Files.list(Paths.get(".")).forEach(System.out::println);

2. 目錄遍歷

// 遞歸遍歷
Files.walk(Paths.get("src"))
    .filter(Files::isRegularFile)
    .filter(p -> p.toString().endsWith(".java"))
    .forEach(System.out::println);

// 帶深度控制
Files.walkFileTree(Paths.get("."), new SimpleFileVisitor<Path>() {
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
        if (file.toString().endsWith(".log")) {
            System.out.println("Log: " + file + " Size: " + attrs.size());
        }
        return FileVisitResult.CONTINUE;
    }
});

3. 文件監視

WatchService watcher = FileSystems.getDefault().newWatchService();
Paths.get("data").register(watcher, StandardWatchEventKinds.ENTRY_CREATE);

while (true) {
    WatchKey key = watcher.take();
    for (WatchEvent event : key.pollEvents()) {
        System.out.println("Event: " + event.kind() + " File: " + event.context());
    }
    key.reset();
}

編碼處理最佳實踐

場景推薦做法避免做法
讀寫文本文件 顯式指定 StandardCharsets.UTF_8 依賴平台默認編碼
屬性文件 Java 9+ Properties.load(Reader) 指定編碼 Properties.load(InputStream) (ISO-8859-1)
控制台輸出 IDE/終端設置 UTF-8,JVM -Dfile.encoding=UTF-8 假設控制台編碼
網絡傳輸 協定規定編碼 (HTTP Header Content-Type charset) 雙方編碼不一致

資源管理鐵律

1. Try-with-resources (Java 7+)

// 自動關閉,異常時也會關閉
try (InputStream is = Files.newInputStream(path);
     BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
    // 使用資源
} // 自動調用 close()

2. 多資源嵌套

try (FileInputStream fis = new FileInputStream("in.txt");
     FileOutputStream fos = new FileOutputStream("out.txt");
     BufferedInputStream bis = new BufferedInputStream(fis);
     BufferedOutputStream bos = new BufferedOutputStream(fos)) {
    // 複製邏輯
}

3. 自定義資源實現 AutoCloseable

public class DbConnection implements AutoCloseable {
    private Connection conn;
    // ...
    @Override
    public void close() throws SQLException {
        if (conn != null) conn.close();
    }
}

// 使用
try (DbConnection db = new DbConnection()) {
    // 數據庫操作
}

總結

  • 字節流:處理圖片、視頻、二進制數據、網絡流
  • 字符流:處理文本文件、配置文件、字符串 (內部編碼 UTF-16)
  • 緩衝流:必須用於文件讀寫,大幅減少系統調用
  • 裝飾器模式:靈活組合功能,按需包裝
  • NIO.2 (Files/Path):現代 API,功能更豐富、語法更簡潔、支援函數式
  • 資源管理:始終使用 try-with-resources,避免洩漏
  • 編碼:顯式指定 UTF-8,拒絕平台默認編碼
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved