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的討論文章。
延伸文章資訊
- 1Java String - Jenkov.com
- 2STR51-J. Use the charset encoder and decoder classes when ...
- 3Convert String to UTF-8 bytes in Java - Tutorialspoint
UTF-8 is a variable width character encoding. UTF-8 has ability to be as condense as ASCII but ca...
- 4Encode a String to UTF-8 in Java - Baeldung
Strings are immutable in Java, which means we cannot change a String character encoding. To achie...
- 5java中string类型转换成UTF-8 - CSDN博客
1、测试方法如下: public static String toUtf8(String str) { return new String(str.getBytes("UTF-8"),"UTF-...