問題:BufferedWriter.write(int c) 寫入單個字符,到底用什麼編碼?能指定 GBK 嗎?
char / int c 在 Java 內部始終是 UTF-16 代碼單元(2 字節,Unicode)BufferedWriter 本身不處理編碼,它只緩衝字符FileWriter 內部包裝的 StreamEncoder)try (BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream("output.txt"),
StandardCharsets.GBK // 或 "GBK", "UTF-8", "UTF-16"
))) {
bw.write('中'); // 字符 '中' → GBK 編碼為 0xD6 0xD0 兩字節寫入文件
bw.write("文");
bw.newLine();
}
Files.newBufferedWriter(
Paths.get("output.txt"),
StandardCharsets.GBK, // 明確指定編碼
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING
);
// FileWriter 內部用 Charset.defaultCharset(),Windows 通常是 GBK,Linux 是 UTF-8
// 跨平台會亂碼,生產環境禁用
try (BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"))) { ... }
// 寫入測試
try (BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream("test_gbk.txt"), "GBK"))) {
bw.write("中文");
}
// 讀取驗證
byte[] bytes = Files.readAllBytes(Paths.get("test_gbk.txt"));
System.out.println(Arrays.toString(bytes));
// GBK: [ -42, -48, -28, -72 ] (0xD6 0xD0 0xE4 0xB8)
// UTF-8: [ -28, -72, -83, -27, -101, -67 ] (0xE4 0xB8 0xAD 0xE6 0x96 0x87)
「BufferedWriter.write(int c) 參數是 int,我傳 0xD6D0 就能寫入 GBK 的『中』了?」
錯。參數 c 只取低 16 位作為 Unicode 代碼點。傳 0xD6D0 會被當作 Unicode 字符 U+D6D0(朝鮮語音節),經 GBK 編碼後寫入完全不同的字節序列。永遠傳 Java char/字符,由編碼器轉換。
new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "GBK"))牢記:不指定編碼就是留坑,生產代碼必須顯式聲明 StandardCharsets.UTF_8 或 "GBK"。