System default encoding --- GBK System default language --- zh
Encode with default encoding
byte[0] = -42 hex string = ffffffd6 byte[1] = -48 hex string = ffffffd0 byte[2] = -50 hex string = ffffffce byte[3] = -60 hex string = ffffffc4
Encode with given encoding : ISO-8859-1
byte[0] = 63 hex string = 3f byte[1] = 63 hex string = 3f
Encode with given encoding : GBK
Encode with given encoding : UTF-8
byte[0] = -28 hex string = ffffffe4 byte[1] = -72 hex string = ffffffb8 byte[2] = -83 hex string = ffffffad byte[3] = -26 hex string = ffffffe6 byte[4] = -106 hex string = ffffff96 byte[5] = -121 hex string = ffffff87 【2】在英文平臺下,測試結果如下:
byte[0] = -28 hex string = ffffffe4 byte[1] = -72 hex string = ffffffb8 byte[2] = -83 hex string = ffffffad byte[3] = -26 hex string = ffffffe6 byte[4] = -106 hex string = ffffff96 byte[5] = -121 hex string = ffffff87 【結論】
在中文平臺下,默認的字符集編碼是GBK,此時如果使用getBytes()或者getBytes("GBK"),則按照GBK的編碼規則將每個中文字符用2個byte表示。所以我們看到"中文"最終GBK編碼結果就是: -42 -48 -50 -60 。-42和-48代表了"中"字,而"-50"和"-60"則代表了"文"字。 在中文平臺下,如果指定的字符集編碼是UTF-8,那么按照UTF-8對中文的編碼規則:每個中文用3個字節表示,那么"中文"這兩個字符最終被編碼成:-28 -72 -83、-26 -106 -121兩組。每3個字節代表一個中文字符。
在中文平臺下,如果指定的字符集編碼是ISO-8859-1,由于此字符集是單字節編碼,所以使用getBytes("ISO-8859-1")時,每個字符只取一個字節,每個漢字只取到了一半的字符。另外一半的字節丟失了。由于這一半的字符在字符集中找不到對應的字符,所以默認使用編碼63代替,也就是?。 在英文平臺下,默認的字符集編碼是Cp1252(類似于ISO-8859-1),如果使用GBK、UTF-8進行編碼,得到的字節數組依然是正確的(GBK4個字節,UTF-8是6個字節)。因為在JVM內部是以Unicode存儲字符串的,使用getBytes(encoding)會讓JVM進行一次Unicode到指定編碼之間的轉換。對于GBK,JVM依然會轉換成4個字節,對于UTF-8,JVM依然會轉換成6個字節。但是對于ISO-8859-1,則由于無法轉換(2個字節--->1個字節,截取了一半的字節),所以轉換后的結果是錯誤的。 相同的平臺下,同一個中文字符,在不同的編碼方式下,得到的是完全不同的字節數組。這些字節數組有可能是正確的(只要該字符集支持中文),也可能是完全錯誤的(該字符集不支持中文)。 記住: 不要輕易地使用或濫用String類的getBytes(encoding)方法,更要盡量避免使用getBytes()方法。因為這個方法是平臺依賴的,在平臺不可預知的情況下完全可能得到不同的結果。如果一定要進行字節編碼,則用戶要確保encoding的方法就是當初字符串輸入時的encoding。