2009-12-15 55 views
2

我在不同的機器上遇到土耳其特殊字符的問題。以下代碼:Java:土耳其編碼Mac/Windows

String turkish = "ğüşçĞÜŞÇı"; 

String test1 = new String(turkish.getBytes()); 
String test2 = new String(turkish.getBytes("UTF-8")); 
String test3 = new String(turkish.getBytes("UTF-8"), "UTF-8"); 

System.out.println(test1); 
System.out.println(test2); 
System.out.println(test3); 

在Mac上,三個字符串與原始字符串相同。在Windows機器上,三條線(用Netbeans 6.7控制檯打印):

?ü?ç?Ü?Ç? 
ğüşçĞÜŞÇı 
?ü?ç?Ü?Ç? 

我沒有得到該問題。

+2

我會檢查Netbeans控制檯編碼(它聽起來可能是ISO-8859-X或Windows1252或...) – ATorras 2009-12-15 13:16:33

+0

我有與Windows 7相同的問題http://stackoverflow.com/questions/1900409/how非英文文本在Java中,它們被表示爲錯誤編碼 – Roman 2009-12-15 13:19:44

+0

@ATorras:精彩的評論!添加它作爲我的問題的答案,我會接受它 – Roman 2009-12-15 13:26:39

回答

11
String test1 = new String(turkish.getBytes()); 

您正在使用包含土耳其字符的Unicode字符串,並使用默認編碼將其轉換爲字節(使用默認編碼通常是一個錯誤)。然後,您再次使用這些字節並將它們解碼爲一個字符串,並再次使用默認編碼。結果是你什麼也沒有達到(除了丟失任何不符合默認編碼的字符)。不管你是否已經通過編碼/解碼週期放了一個字符串,System.out.println(test1)所做的沒有影響,因爲它仍然打印一個字符串而不是字節。

String test2 = new String(turkish.getBytes("UTF-8")); 

編碼爲UTF-8,然後使用默認編碼進行解碼。在Mac上,默認編碼是UTF-8,所以這沒有任何作用。在Windows上,默認編碼從不是UTF-8,所以結果是錯誤的字符。

String test3 = new String(turkish.getBytes("UTF-8"), "UTF-8"); 

確實沒有。

要使用與默認編碼不同的編碼將字符串寫入標準輸出,您需要創建一個類似new OutputStreamWriter(System.out, "cp1252")的編碼器,並將字符串內容發送到該編碼器。

但是在這種情況下,它看起來像控制檯正在使用Windows代碼頁1252西歐(+1 ATorres)。這裏根本沒有編碼不匹配的問題,所以你將無法通過重新編碼字符串來解決它!

默認編碼cp1252與控制檯的編碼相匹配,只不過cp1252完全不包含土耳其文字符ğşĞŞı。您可以在cp1252,üçÜÇ中看到的其他字符,通過就好了。除非您可以重新配置控制檯以使用包含所需字符的其他編碼,否則您將無法輸出這些字符。

推測在土耳其語Windows安裝中,默認代碼頁將是cp1254,而您將獲得您期望的字符(但其他字符不起作用)。您可以通過在區域和語言選項控制面板應用程序中更改「用於非Unicode應用程序的語言」設置來測試此設置。

不幸的是,沒有Windows語言環境使用UTF-8作爲默認代碼頁。使用stdio流功能將非ASCII輸出放到控制檯上並不是真的可靠。有一個Win32 API可以直接將Unicode寫入控制檯,但不幸的是沒有多少使用它。

+0

謝謝!我遇到了類似的問題,並且在Windows上更改區域設置可解決此問題。或者說,我根據你的回答意識到確實沒有問題,而罪魁禍首是控制檯。再次感謝您的回答,在這個國際化這個混亂的話題上是至關重要的。 – Sabuncu 2012-04-16 21:16:15

5

不要依賴控制檯或默認平臺編碼。總是指定諸如getBytes之類的調用的字符編碼以及採用字節數組的字符串構造函數的字符編碼,並且如果要檢查字符串的內容,請輸出每個字符的unicode值。

我也建議要麼限制你的源代碼使用ASCII(和爲\ uXXXX編碼非ASCII字符)明確指定的字符編碼,當你編譯。

現在,你想解決什麼大問題?

+2

+1。遺憾的是,很多Java stdlib都有編碼的默認參數;幾乎沒有理由依賴默認編碼,它只會鼓勵可怕的錯誤和部署問題。 – bobince 2009-12-15 15:15:23

2

您可能正在處理默認編碼的不同設置。

java -Dfile.encoding=utf-8 

java -Dfile.encoding=something else 

或者,你可能只是看到了蘋果終端窗口用UTF-8的事實,和Windows DOS窗口確實在UTF-8 工作。

根據Skeet先生,您有第三個可能的問題,那就是您試圖在源代碼中嵌入UTF-8字符。根據編譯器選項,你可能會或可能不會得到你想要的。將這些數據放在一個屬性文件中,或使用\ u轉義。

最後,也是根據Skeet先生,永遠不要調用零參數getBytes()。

0

如果您使用的是AspectJ編譯器,不要忘記將其編碼設置爲UTF-8。我一直在努力尋找這個小時。