字串編碼


相信現在或未來的日子,在Java中你不會只處理英文,所以你要瞭解Java中如何處理中文!在正式介紹Java如何處理字串編碼前,容我問一句:你寫的.java原始碼是什麼編碼?

這其實是個簡單但蠻重要的問題,但事實上有許多人答不出來。如果是正體中文Windows,建立純文字檔案重新命名為.java,使用Windows預設純文字編輯器,那麼應該是Big5編碼。如果在NetBeans中建立.java原始碼,預設應該是UTF-8編碼。如果是在Eclipse中建立.java原始碼,而Eclipse運行在正體中文Windows中,預設應該是Big5編碼。

知道這個問題的答案後,再繼續想想,之前章節談過Java支援Unicode,所以寫下一個英文字元或寫下一個中文字元,都是兩個位元組。那麼你是否想過,明明你的Windows純文字編輯器是Big5編碼,為什麼會寫下的字串在JVM中會是Unicode?如果你在一個Main.java中寫下以下的程式碼並編譯:

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello");
        System.out.println("哈囉");
    }
}

如果你的作業系統預設編碼是Big5,而你的文字編輯器是使用Big5編碼,那麼你如下執行編譯:

> javac Main.java

產生的.class檔案,使用反組譯工具還原的程式碼中,會看到以下的內容:

public class Main {
    public static void main(String args[]) {
        System.out.println("Hello");
        System.out.println("\u54C8\u56C9");
    }
}

Java中字元可以用\uxxxx來表示,其中xxxx是字元的Unicode編碼。上面反組譯的程式中,"\u54C8\u56C9"就是"哈囉"的Unicode碼點(Code point),JVM在載入.class之後,就是讀取Unicode碼點並產生對應的字串物件,而不是最初你在原始碼中寫下的"哈囉"。

那麼編譯器怎麼知道要將中文字元轉為哪個Unicode編碼?當你使用javac指令沒有指定-encoding選項時,會使用作業系統預設編碼,如果你的文字編譯器是使用UTF-8編碼,那麼編譯時就要指定-encoding為UTF-8,如此編譯器才會知道用何種編譯讀取.java的內容。例如:

> javac -encoding UTF-8 Main.java

在Windows中不要使用純文字編輯器轉存的UTF-8文件來撰寫Java程式,Windows的純文字編輯器會在檔首加上BOM,這不在UTF-8規範中,幾乎只有Microsoft自家程式才會認識BOM。簡單地說,javac看到BOM會無法編譯。正如第2章提示過的,建議可以使用 NotePad++,它可以讓你很方方便地選擇文字編碼。

想要知道更多編碼問題,可以進一步參考 亂碼 1/2