2011-08-05 45 views
1

我認爲UCS-2到ISO-8859-1是一樣Java的String.getBytes(「ISO-8859-1」)是否返回字符串中每個2字節字符的第一個字節?

rawData = new byte[data.length()]; 
    for(int i=0; i<data.length(); i++) { 
     rawData[i] = (byte)(data.charAt(i) & 0xff); 
    } 

這似乎是假的。爲什麼上面的代碼不等於data.getBytes("ISO8859_1")呢?我在Android上。

事實上,事實證明,我的一些角色是0xf700 & (byte)。出於某種原因,當您使用XMLHttpRequestCharset: x-user-defined獲取二進制文件時會發生這種情況。當轉換爲latin1時,這些字符會變成?(問號)。

回答

3

每THW的Android documentation

當此字符串不能在指定的字符集來表示的行爲是不確定的。

實際上,這個調用最終會變成一個明確的Charset,它會用一些替換序列替換一些不可翻譯的字符。在Sun JDK中,這是一個單字節值64('?')。

但是,在您對先前答案的評論中,您保證在字符串中沒有大於'0xFF'的字符值,那麼您做錯了什麼。 ISO-8859-1是UCS-2/UTF-16的一個子集。

+0

不,這將是一個「真子集」,如果當'UTF-16'和編碼'字符串導致相同的字節ISO-8859 -1',這顯然沒有。 –

+0

我可能會做錯事。我將通過比較來自兩種不同方法的兩個字節來仔細檢查。 – joeforker

2

原因已經由parsifal的答案解釋。只是爲了完整性,這裏是這相當於data.getBytes("ISO-8859-1")代碼(假設這個字符串是一個純粹的UCS-2字符串,沒有代理對):

byte[] rawdata = new byte[data.length()]; 
for(int i = 0; i < data.length; i++) { 
    char c = data.charAt(i); 
    if (c > 255) { 
     rawData[i] = (byte)'?'; 
    } 
    else { 
     rawData[i] = (byte)c; 
    } 
} 

隨着替代品(如真正的UTF-16)開始有點更復雜:

byte[] rawData = new byte[data.length()]; 
int j = 0; 
for(int i = 0; i < data.length; i++, j++) { 
    int c = data.codePointAt(i); 
    if(c < 0x100) { 
     rawData[j] = (byte)c; 
    } 
    else { 
     rawData[j] = (byte)'?'; 
     if(c >= 0x10000) { 
      // surrogate pair 
      i++; 
     } 
    } 
} 
if(j < rawData.length) { 
    rawData = Arrays.copyOf(rawData, j); 
} 

或者,只是用charAt()

byte[] rawData = new byte[data.length()]; 
int j = 0; 
for(int i = 0; i < data.length; i++, j++) { 
    char c = data.charAt(i); 
    if(c < 0x100) { 
     rawData[j] = (byte)c; 
    } 
    else { 
     rawData[j] = (byte)'?'; 
     if(Character.isHighSurrogate(c) && Character.isLowSurrogate(data.charAt(i+1))) { 
      // surrogate pair 
      i++; 
     } 
    } 
} 
if(j < rawData.length) { 
    rawData = Arrays.copyOf(rawData, j); 
} 
相關問題