Можно ли создать пустую строку Java из непустого байтового массива UTF-8? - PullRequest
3 голосов
/ 07 мая 2009

Я пытаюсь что-то отладить, и мне интересно, может ли следующий код вернуть true

public boolean impossible(byte[] myBytes) {
  if (myBytes.length == 0)
    return false;
  String string = new String(myBytes, "UTF-8");
  return string.length() == 0;
}

Есть ли какое-то значение, которое я могу передать, которое вернет true? Я возился с передачей только первого байта двухбайтовой последовательности, но он по-прежнему выдает строку из одного символа.

Для пояснения, это произошло на чипе PowerPC в коде Java 1.4, скомпилированном через GCJ в собственный двоичный исполняемый файл. Это в основном означает, что большинство ставок отменены. Меня больше всего интересует, «нормальное» ли поведение Java или какие-либо обещания в спецификации Java.

Ответы [ 4 ]

6 голосов
/ 07 мая 2009

Согласно javadoc для java.util.String, поведение новой строки (byte [], "UTF-8") не указывается, когда байтовый массив содержит недопустимые или неожиданные данные. Если вы хотите большей предсказуемости в результирующей строке, используйте http://java.sun.com/j2se/1.5.0/docs/api/java/nio/charset/CharsetDecoder.html.

1 голос
/ 07 мая 2009

Если Java правильно обрабатывает метку BOM (что я не уверен, исправили ли они это еще), то должна быть возможность ввести байтовый массив только с помощью спецификации (U + FEFF который находится в UTF-8 (последовательность байтов EF BB BF) и получить пустую строку.


Обновление:

Я тестировал этот метод со всеми значениями 1-3 байта. Никто из них не возвратил пустую строку на Java 1.6. Вот тестовый код, который я использовал с разными длинами байтового массива:

public static void main(String[] args) throws UnsupportedEncodingException {
    byte[] test = new byte[3];
    byte[] end = new byte[test.length];

    if (impossible(test)) {
        System.out.println(Arrays.toString(test));
    }
    do {
        increment(test, 0);
        if (impossible(test)) {
            System.out.println(Arrays.toString(test));
        }
    } while (!Arrays.equals(test, end));

}

private static void increment(byte[] arr, int i) {
    arr[i]++;
    if (arr[i] == 0 && i + 1 < arr.length) {
        increment(arr, i + 1);
    }
}

public static boolean impossible(byte[] myBytes) throws UnsupportedEncodingException {
    if (myBytes.length == 0) {
        return false;
    }
    String string = new String(myBytes, "UTF-8");
    return string.length() == 0;
}
1 голос
/ 07 мая 2009

Возможно.

Из документации по API Java 5 «Поведение этого конструктора, когда указанные байты недопустимы в заданной кодировке, не определено.»

Полагаю, это зависит от: Какую версию Java вы используете Какой поставщик написал вашу JVM (Sun, HP, IBM, с открытым исходным кодом и т. Д.)

Как только документы говорят "не указано", все ставки отменяются.

Редактировать: побежден Трей Воспользуйтесь его советом по использованию CharsetDecoder

0 голосов
/ 07 мая 2009

UTF-8 - это схема кодирования переменной длины, в которой большинство "нормальных" символов являются однобайтовыми. Так что любой непустой байт [] всегда будет переводиться в строку, я бы подумал.

Если вы хотите воспроизвести его, то напишите модульный тест, который повторяет все возможные байтовые значения, передавая массив из одного значения этого значения, и утверждает, что строка не пустая.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...