翻譯公司很多人用 Java 處置到中文資料時,常會泛起亂碼翻譯關於 Java 和中文兼容性的問題,實在讓很多法式員為此傷透腦筋,相幹的問題每隔幾天就會呈現在收集上。為了舒緩您緊蹙的眉頭,華頓翻譯公司特別寫了這系列文章,解說 Java 牽涉到文字時的內部處置懲罰體例,供讀者參考翻譯讀完本系列文章以後,囫囵吞棗者可以治標,充裕理解者可以治本。本文貴在原理說明註解,別光是囫圇吞棗翻譯
快速解決之道
若是
1. 檢查操作系統設定:先檢查你的操作系統,肯定國籍說話資料是「Traditional Chinese(Taiwan)」翻譯國籍說話資料的設定會影響 Java 編譯器與JRE的判斷翻譯我之前就是因為國籍資料設定不正確,出了一堆 Java 和中文不兼容的怪事翻譯
2. 更新 Java 情況版本:改用最新版的 JDK,新版本的 JDK 說不定已經解決你原本的問題翻譯請注意:某些 Java IDE 所用的編譯器和 JRE 是不兼容於中文的(我遇過如許的景遇),你最好能把 Java IDE 的 JDK 指到新版的 JDK翻譯另外,如果數據庫取回的資料是亂碼,換別套或更新 JDBC 驅動法式碰運氣。
若是照樣無法解決,請詳細閱讀下面各末節的內容,細心斟酌你的錯誤地點翻譯
Unicode、UTF-16、UTF-8
Java 內部處理字符使用的字序體例是 Unicode,這是一種通行全球的編碼體例。Unicode 因為必需將中、韓、日、英、法、阿拉伯……等許多國家所利用的文字都納入,今朝已包括了六萬多個字符,所以 Unicode 利用了 16 個位來為字符編碼。因為 Unicode 使用了 16 位編碼,所以每一個字符都用 16 位來貯存或傳輸是很自然的事,這類貯存或傳輸的格局稱為 UTF-16(是不是很像戰鬥機的名字)。如果
關於 Unicode 的編碼,請查閱「The Unicode Standard翻譯社 Version 3.0」一書(Addison-Wesley 出書);關於 UTF-8 編碼,請查閱「Java I/O」一書的 399 頁(O'Reilly 出版)。關於 Java Class File 的格局與 Constant Pool,請查閱「Java Virtual Machine」一書(O'Reilly出版)。
Unicode 與繁體中文編碼的互轉
固然 Java 內部完全地利用 Unicode,然則
想知道你的 JDK 或 JRE 會用什麼樣的編碼體式格局來和操作系統溝通,請執行下面的 Java 法式:
public class ShowNativeEncoding {
public static void main(String[] args) {
String enc = System.getProperty("file.encoding");
System.out.println(enc);
}
}
假如履行結果不是下面的字符串之一,那麼你的操作系統國籍說話設定可能就有問題了:
· Big5:這是繁體中文 de facto 標準。
· CNS11643:台灣的官方標準繁體中文編碼。
· Cp937:繁體中文加上 6204 個使用者自定的字符
· Cp948:繁體中文版 IBM OS/2 用的編碼方式。
· Cp964:繁體中文版 IBM AIX 用的編碼體例。
· EUC_TW:台灣的增強版 Unicode。
· ISO2022CN:編碼中文的一套標準。
· ISO2022CN_CNS:編碼中文的一套標準,繁體版,襲自 CNS11643。
· MS950 或 Cp950:ASCII + Big5,用於台灣和香港的繁體中文 MS Windows操作系統。
· Unicode:有順序記號的 Unicode。順序記號佔用兩個 byte,若是其值是0xFEFF,表示利用 big-endian(由大到小)的順序為 Unicode 編碼;如果其值是 0xFFFF,默示利用 little-endian(由小到大)的次序為 Unicode 編碼翻譯
· UnicodeBig:使用 big-endian(由大到小)的順序為 Unicode 編碼。
· UnicodeLittle:使用 little-endian(由小到大)的次序為 Unicode 編碼。
· UTF8:利用 UTF-8 為 Unicode 編碼翻譯
關於 Big 5 編碼,請查閱「CJKV Information Processing」一書的附錄 H(O'Reilly出書)。
編譯時的注意事項
編譯的時辰,如果
平常在編譯階段,會造成的毛病有下列幾種可能:
1. 若是操作系統的國籍資料設定錯誤,會造成 javac 編譯器獲得的編碼信息是錯的翻譯
2. 較低劣的編譯器可能沒有自動扣問操作系統的編碼方式,而是採用編譯器預設的編碼體例。
3. 假如原始法式不是用編譯當時操作系統預設的編碼體例存盤的,也會造成毛病。例如說,原始法式文件是台灣程序員寫的,在繁體中文版的 Windows上以 MS950 編碼存盤,再經過收集傳送到泰國,在泰文版的 Windows 上編譯(泰文版 Windows 預設的檔案編碼體例是 MS874)。
這種因為原始法式文件編碼方式和編譯器無法匹配所釀成的問題,輕則編譯成功但履行時文字呈現亂碼或泛起 Error/Exception,重則沒法成功編譯翻譯這時候,你需要自動透過「-encoding」選項來指定原始法式的編碼方式,編譯器會以你指定的編碼為主,不會再去扣問操作系統。下面的例子,我們告知編譯器「TaiwanClass.java」是以繁體中文版 Windows 的「MS950」編碼的:
javac –encoding MS950 TaiwanClass.java
如果你手上只有某 class 文件,沒有原始程序文件,並且你確定其 constant pool 的UTF-8 字段編碼錯誤,你有兩種體例可以用來批改編碼:
1. 先反編譯,獲得原始程序,再點竄,編譯翻譯
2. 或直接哄騙 bytecode 編纂軟件,直接修改 class 文件。
I/O 轉碼
Java 現行的 IO 一概利用 Stream 的體例,相關的種別都放在 java.io 中翻譯輸出 binary 的資料利用 OutputStream 的子種別,輸入 binary 的資料利用 InputStream 的子類別,輸出文字的資料利用 Writer 的子類別,輸入文字的資料利用 Reader 的子類別。
你可能會感覺很希奇:「有需要用分歧的方式來處置文字和 binary 嗎?文字資料不也是 binary 的一種?」沒錯,其實他們異常近似,最大的差異在於,InputStream/OutputStream 會原封不動地傳送資料,可是 Reader/Writer 會將資料看成文字看待,所以 Reader/Writer 在「需要時」會把(文字)資料轉碼。什麼時候才是所謂的「需要時」呢?
Java 的 Stream(包孕 Reader 和 Writer)是可以相互串接的翻譯當 Reader 的資料來源是另外一個 Reader 時,不轉碼,當 Reader 的資料來源是一個 InputStream 時,就會轉碼。當 Writer 的資料去處是另外一個 Writer 時,不轉碼,當 Writer 的資料行止是一個 OutputStream 時,就會轉碼。
由什麼碼轉成什麼碼?這是可以指定的翻譯因為轉碼只産生在 Reader/InputStream 的接壤處與 Writer/OutputStream 的交壤處,所以正是由 InputStreamReader 和 OutputStreamWriter 此二種別負責,下面兩個 constructor 的第二個參數,恰是用來指定轉碼的方式。
public InputStreamReader(InputStream in, String enc)
throws UnsupportedEncodingException;
public OutputStreamWriter(OutputStream out, String enc)
throws UnsupportedEncodingException;
InputStreamReader 負責將 enc 的編碼體例轉成 Unicode(因為資料是從「外部」送過來給「內部」的),OutputStreamWriter 負責將 Unicode 的編碼體例轉成 enc(因為資料要從「內部」送給「外部」)。JRE 內部當然都一定是用 Unicode 編碼,而外部的編碼就紛歧定,要看當時的環境為何。
請注意:即便
假如你清楚地知道
檔案 I/O 轉碼
如果你是在泰文版的 Windows 上,想讀取用 MS950 編碼的繁體中文文字文件,你就必需自動指定編碼,不行以直接用 FileReader,不然無法成功讀取。方式以下:
FileInputStream fis = new FileInputStream(fileName);
InputStreamReader reader = new InputStreamReader(fis, "MS950");
然後,透過 Reader 讀出來的就會是准確的中文。
網絡 I/O 轉碼
若是你的收集法式採用 TCP,那麼
InputStream is = mySocket.getInputStream();
InputStreamReader reader = new InputStreamReader(is, "MS950");
若是你的收集法式採用 UDP,
若是你的網絡法式採用 RMI,那你完全不消為這部分的轉碼費心,字符串直接用 Unicode 在收集上傳遞給另一個 JRE,不需要轉碼。
保持刑案現場
若是你不知道你的 I/O 資料來源或去處是用何種編碼體例,那麼你最好不要用 Reader 和 Writer,而應當直接用 InputStream 和 OutputStream,因為與其被 Reader 和 Writer 胡亂編碼以後造成信息遺失或錯亂,不如保持資料的完全不變,留待今後進一步解讀翻譯
字符串和 byte 數組的轉碼
java.lang.String 種別是 Java 字符串對象的種別,Java 字符串對像既然是活在 JRE 內部,當然就必然是用 Unicode 編碼。假如你需要將 String 對像和 byte 數組互轉,你可使用:
String(byte[] bytes, int offset翻譯社 int length翻譯社 String enc);
或
String(byte[] bytes, String enc);
來將用 enc 編碼的 byte 數組,轉成 Unicode 的 String 對象翻譯你也可以利用 String 對像所供應的:
byte[] getBytes(String enc)
來將 String 對像轉成 byte 數組。
別的,你也能夠透過 ByteArrayInputStream 或 ByteArrayOutputStream 串接到 InputStreamReader 或 OutputStreamWriter,來達到轉碼的目標翻譯
文章來自: https://blog.xuite.net/evan_0412/wretch/169912286-JAVA%E4%BA%82%E7%A2%BC%E5%95%8F%E9%A1%8C%EF%BC%88%有關各國語文翻譯公證的問題歡迎諮詢華頓翻譯公司02-77260932
- Oct 25 Thu 2018 08:06
JAVA亂碼問題(轉載自網路) @ Java A+
close
文章標籤
全站熱搜
留言列表
發表留言