從 JDK 18 開始, Java 預設編碼不再是使用平台的編碼, 而是 UTF-8 編碼, 以下是分別以 JDK 17 取得預設編碼的結果:
# jshell
| Welcome to JShell -- Version 17.0.6
| For an introduction type: /help intro
jshell> import java.nio.charset.Charset
jshell> Charset.defaultCharset()
$2 ==> x-windows-950
如果使用 JDK 18, 結果如下:
# jshell
| Welcome to JShell -- Version 18.0.1.1
| For an introduction type: /help intro
jshell> import java.nio.charset.Charset
jshell> Charset.defaultCharset()
$2 ==> UTF-8
如果你的程式在讀取檔案時都沒有指定編碼, 就要注意是否會因為編碼關係而讀取錯誤。
以指定編碼讀取檔案
如果想要讀取不同編碼的檔案, 就必須在開啟檔案時設定編碼。以下以在 JDK 18 的環境下讀取 big5 編碼的檔案為例:
我是 big-5
要指定編碼, 可以使用 java.nio.charset.Charset 類別的 forName 方法, 傳入編碼的名稱即可:
import java.nio.charset.*;
import java.io.*;
public class RF {
public static void main(String[] args) {
char[] c = new char[1];
try {
FileReader f = new FileReader("test.txt", Charset.forName("big5"));
while(f.read(c, 0, 1) != -1) {
System.out.print(c[0]);
}
}
catch(Exception e) {
}
}
}
可用的編碼名稱可以參考 2 Supported Encodings 的列表。
對於一些國際標準的編碼, 則是在 java.nio.charset.StandarCharset 類別中已經有建好的編碼物件, 分別是 US_ASCII、ISO_8859_1、UTF_16、UTF_16BE、UTF_16LE、UTF_8, 可以直接取用。
查詢目前使用編碼
如果你擔心預設的編碼不是 UTF8, 也可以透過 Charset 的 defaultCharset() 方法查看:
jshell> import java.nio.charset.Charset
jshell> Charset.defaultCharset()
$2 ==> UTF-8
或是也可以檢查系統變數 file.encoding:
jshell> System.getProperty("file.encoding")
$3 ==> "UTF-8"
系統變數 native.encoding 則是作業系統平台本身採用的編碼:
jshell> System.getProperty("native.encoding")
$4 ==> "MS950"
MS950 就是 Windows 的 CP950, 也就是 Big5 編碼。
輸出時的編碼
輸出時預設會採用執行環境的編碼, JDK 18 開始可以由 System.out.charset().name() 取得, 以下是簡單的測試程式:
public class SysOutEncoding {
public static void main(String args[]) {
System.out.println(System.out.charset().name());
}
}
以下是在 Powershell 7 的實際執行結果:
# chcp
Active code page: 65001
# java .\SysOutEncoding.java
UTF-8
如果改到 cmd 下執行:
>chcp
使用中的字碼頁: 950
>java SysOutEncoding.java
x-windows-950
不過要注意的是, 在 jshell 中, 似乎都是採用系統預設的編碼, 像是在已經設定為 UTF-8 的 Powershell 7 中:
jshell> System.out.charset().name()
$1 ==> "x-windows-950"
jshell> System.getProperty("native.encoding")
$2 ==> "MS950"
jshell> System.out.println("測試")
����
由於輸出編碼與 shell 不同, 所以會變成亂碼。如果想要更改 System.out
的輸出編碼, 可以這樣做:
jshell> System.setOut(new PrintStream(System.out, true, "UTF-8"))
jshell> System.out.println("測試")
測試
輸出結果就正確了。
Top comments (0)