01.06 深入分析Java中String.getBytes()編碼問題

String.getBytes() 方法返回一個字符串的字節數組,這個沒有什麼問題。但需要注意的是,該方法將返回操作系統默認的編碼格式的字節數組。這樣,在一個平臺(如windows)上運行正常的系統,部署到另外一個平臺(如linux)上可能會產生問題。

一、getBytes() 方法

getBytes() 方法有兩種形式:

getBytes(String charsetName): 使用指定的字符集將字符串編碼為 byte 序列,並將結果存儲到一個新的 byte 數組中。

getBytes(): 使用平臺的默認字符集將字符串編碼為 byte 序列,並將結果存儲到一個新的 byte 數組中。

先看一段示例代碼,以及其輸出結果:

<code>package com.rickie;

public class GetBytesDemo {
private String str = "Hello中國上海";

public static void main(String[] args) {
GetBytesDemo getBytesDemo = new GetBytesDemo();
getBytesDemo.execute();
getBytesDemo.execute2();
}

private void execute() {
byte[] bytes = str.getBytes();
System.out.println("bytes length is:" + bytes.length);
}

private void execute2() {
byte[] bytesISO8859 = null;
byte[] bytesGBK = null;
byte[] byteUTF8 = null;

try {
bytesISO8859 = str.getBytes("ISO-8859-1");
bytesGBK = str.getBytes("GBK");
byteUTF8 = str.getBytes("UTF-8");
} catch (Exception e) {

e.printStackTrace();
}

System.out.println("ISO-8859-1: " + bytesISO8859.length);
System.out.println(arrayToString(bytesISO8859));

System.out.println("GBK: " + bytesGBK.length);
System.out.println(arrayToString(bytesGBK));

System.out.println("UTF-8: " + byteUTF8.length);
System.out.println(arrayToString(byteUTF8));
}

public static final String arrayToString(byte[] bytes) {
StringBuffer buff = new StringBuffer();
for (int i = 0; i < bytes.length; i++) {
buff.append(bytes[i] + " ");
}
return buff.toString();
}
}/<code>

上面我們將字符串分別提取ISO-8859-1、GBK、UTF-8三種編碼格式的字節數組。

在Mac平臺上,運行上述示例代碼的輸出結果:

深入分析Java中String.getBytes()編碼問題


ISO-9985-1格式的字節數組長度為9,中文字符都變成了63,ASCII碼為63的是符號?。在英文平臺中,一般的默認編碼是"ISO-8859-1",每個字符都只取一個字節(而不管是否非拉丁字符)。GBK格式的字節數組長度為13,UFT-8編碼格式的字節數組長度為17。

String採用一種靈活的方式進行存儲。在String中,一個英文字符佔1個字節,而中文字符根據編碼的不同所佔字節數也不同。在UTF-8編碼下,一箇中文字符佔3個字節;而使用GBK編碼時一箇中文字符佔2個字節。


二、通過new String(byte[], decode) 方式還原字符串

與getBytes() 方法相對應,可以通過 new String(byte[], decode) 來還原字符串,實際上是用decode指定的編碼來將byte[] 解析成字符串。

對上面的代碼進行更新,再次運行,查看輸出結果。

<code>System.out.println("ISO-8859-1: " + bytesISO8859.length);
System.out.println(arrayToString(bytesISO8859));

System.out.println(new String(bytesISO8859, "ISO-8859-1"));

System.out.println("GBK: " + bytesGBK.length);
System.out.println(arrayToString(bytesGBK));
System.out.println(new String(bytesGBK, "GBK"));

System.out.println("UTF-8: " + byteUTF8.length);
System.out.println(arrayToString(byteUTF8));
System.out.println(new String(byteUTF8, "UTF-8"));/<code>

下面是還原的字符串結果:

深入分析Java中String.getBytes()編碼問題


只有ISO-8859-1編碼輸出的中文是?字符,為什麼使用ISO-8859-1編碼再組合之後,無法還原中文字呢?

其實原因很簡單,因為ISO-8859-1編碼的編碼表中,根本就沒有包含中文字符,當然也就無法通過getBytes(“ISO-8859-1");來得到正確的中文在ISO-8859-1中的編碼值了,所以再通過new String()來還原就無從談起了。



分享到:


相關文章: