Java String.getBytes ("ISO-8859-1") возвращает первый байт каждого 2-байтового символа в строке? - PullRequest
1 голос
/ 06 августа 2011

Я думал, что UCS-2 для ISO-8859-1 был таким же, как

    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). По какой-то причине это происходит, когда вы выбираете двоичный файл с XMLHttpRequest и Charset: x-user-defined. При преобразовании в latin1 эти символы превращаются в ? (вопросительные знаки).

Ответы [ 2 ]

3 голосов
/ 07 августа 2011

в месяц для Android документация :

Поведение, когда эта строка не может быть представлена ​​в именованном кодировке, не определено.

На практике этот вызов заканчивается как вариант, который принимает явный Charset, который заменит некоторую последовательность замены для непереводимых символов. В Sun JDK это однобайтовое значение 64 ('?').

Тем не менее, в своем комментарии к предыдущему ответу вы гарантируете, что в строке нет значений символов больше 0xFF, тогда вы делаете что-то не так. ISO-8859-1 является правильным подмножеством UCS-2 / UTF-16.

2 голосов
/ 07 августа 2011

Причину уже объяснил ответ Парсифаля. Просто для полноты, вот код, который эквивалентен 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...