Java 的字串
文章推薦指數: 80 %
任何一本Java 入門的書都會談到,Java 的字串使用Unicode,那麼是否想過,明明你的文字編輯器是使用MS950 編碼,為什麼會寫下的字串在JVM 中會是Unicode?如果在一個.
回Encoding目錄
任何一本Java入門的書都會談到,Java的字串使用Unicode,那麼是否想過,明明你的文字編輯器是使用MS950編碼,為什麼會寫下的字串在JVM中會是Unicode?如果在一個Main.java中寫下以下的程式碼並編譯:
publicclassMain{
publicstaticvoidmain(String[]args){
System.out.println("Test");
System.out.println("測試");
}
}
如果作業系統預設編碼是MS950,而文字編輯器是使用MS950編碼,那麼你如下執行編譯:
C:\workspace>javacMain.java
產生的.class檔案,使用任何的反組譯工具還原回來的程式碼中,你可能會看到以下的內容:
importjava.io.PrintStream;
publicclassMain{
publicMain(){}
publicstaticvoidmain(Stringargs[]){
System.out.println("Test");
System.out.println("\u6E2C\u8A66");
}
}
其中"\u6E2C\u8A66"就是"測試"的Unicode碼點表示,JVM在載入.class之後,就是讀取Unicode編碼並產生對應的字串物件,而不是最初在原始碼中寫下的"測試"。
那麼編譯器怎麼知道要將中文字元轉為哪個Unicode編碼?正如〈你的原始碼是什麼編碼?〉談過的,當使用javac指令沒有指定-encoding選項時,會使用作業系統預設編碼,如果文字編譯器是使用UTF-8編碼,那麼編譯時就要指定-encoding為UTF-8,如此編譯器才會知道用何種編譯讀取.java的內容。
例如:
C:\workspace>javac-encodingUTF-8Main.java
那麼啟動JVM之後,字串的實作位元組呢?如果想取得字串的位元組資料,可以使用String的getBytes()方法。
例如:
packagecc.openhome;
importstaticjava.lang.System.out;
publicclassMain{
publicstaticvoidmain(String[]args)throwsException{
print("UTF-16","測試".getBytes("UTF-16"));
print("UTF-8","測試".getBytes("UTF-8"));
print("Big5","測試".getBytes("Big5"));
print("default","測試".getBytes());
}
privatestaticvoidprint(Stringencoding,byte[]bytes){
out.printf("%s\t",encoding);
for(byteb:bytes){
out.printf("%-3h",b&0x00FF);
}
out.println();
}
}
getBytes()在使用時,可以指定用哪個編碼取得字串的位元組序列,上面這個程式,分別將「測試」以UTF-16、UTF-8、Big5三種編碼取得位元組序列,結果如下,可以用十六進位編輯器來印證「測試」在這幾種編碼下,位元組序列是不是與執行結果相同(注意純文字中UTF-16開頭若是fe、ff,那是BOM):
UTF-16feff6e2c8a66
UTF-8e6b8ace8a9a6
Big5b4fab8d5
defaultb4fab8d5
getBytes()可以不指定編碼呼叫,此時會用〈JVM預設編碼〉,在啟動JVM沒有任何指定的情況下,就會與作業系統預設編碼一致,上面的執行結果是在正體中文Windows下執行的,所以getBytes()預設就會使用Big5來取得位元組序列。
如果有一個位元組陣列,可以用來建構字串,建構時可指定以何種編碼方式來解釋所提供的位元組陣列。
例如:
packagecc.openhome;
importstaticjava.lang.System.out;
publicclassMain{
publicstaticvoidmain(String[]args)throwsException{
out.println(newString(toBytes(0xfe,0xff,0x6e,0x2c,0x8a,0x66),"UTF-16"));
out.println(newString(toBytes(0xe6,0xb8,0xac,0xe8,0xa9,0xa6),"UTF-8"));
out.println(newString(toBytes(0xb4,0xfa,0xb8,0xd5),"Big5"));
out.println(newString(toBytes(0xb4,0xfa,0xb8,0xd5)));
}
privatestaticbyte[]toBytes(int...ints){
byte[]bytes=newbyte[ints.length];
for(inti=0;i
如果這是資料庫的某個欄位,現在可以直接撰寫程式取得其它欄位字串結果,使用ISO-8859-1(或windows-1252,不過這比較不可能)取得位元組陣列,再用以建立Big5字串,看看結果是否都是可辨識的,如果確認是的話,就可以重新將這些欄位用正確的編碼寫回資料庫。
PS.上面這個範例來自JWorld@TW的討論文章。
延伸文章資訊
- 1Byte Encodings and Strings (The Java™ Tutorials ...
Byte Encodings and Strings ... If a byte array contains non-Unicode text, you can convert the tex...
- 2Encode a String to UTF-8 in Java - Stack Abuse
Encoding a String in Java simply means injecting certain bytes into the byte array that constitut...
- 3Java String Encoding - Javatpoint
In Java, when we deal with String sometimes it is required to encode a string in a specific chara...
- 4Java String Encoding - Javatpoint
- 5Encode String in UTF-8 in Java | Delft Stack
Encode String in UTF-8 in Java · Encode a String to UTF-8 by Converting It to Bytes Array and Usi...