Отличия Java UTF-8 - PullRequest
       0

Отличия Java UTF-8

8 голосов
/ 22 июня 2011

JavaDoc сообщает "Нулевой байт '\ u0000' кодируется в 2-байтовом формате, а не в 1-байтовом, так что закодированные строки никогда не имеют встроенных нулей."

Но что это вообще значит? Что такое встроенный нуль в этом контексте? Я пытаюсь преобразовать сохраненную в Java строку UTF-8 в "настоящую" UTF-8.

Ответы [ 5 ]

16 голосов
/ 22 июня 2011

В C строка заканчивается байтовым значением 00.

Дело в том, что вы можете иметь строки с 0 символами в строках Java, но во избежание путаницы при передаче строки в C (в котором написаны все нативные методы) символ кодируется другим способом а именно как два байта

11000000 10000000

(в соответствии с javadoc) ни один из которых на самом деле не 00.

Это хак, чтобы обойти то, что вы не можете легко изменить.

Также обратите внимание, что это действительно UTF-8 и правильно декодируется до 00.

4 голосов
/ 22 июня 2011

Отсутствие «встроенных нулей» означает, что необработанные данные не содержат ни одного 0x00 (NULL) байта.

\u0000 кодируется в (двоичный) 11000000 10000000, (шестнадцатеричный) 0xC080.

1 голос
/ 22 июня 2011

Это только для метода writeUTF объекта DataOutputStream, а не для обычных преобразованных потоков (OutputStreamWriter или подобных).

Это означает, что если у вас есть строка "\u0000", она будет закодирована как 0xC0 0x80 вместо просто 0x00.

И наоборот, эта последовательность 0xB0 0x80, которая никогда не встречается в обычных строках UTF-8, представляет собой нулевой символ.

Кроме того, документация, на которую вы ссылаетесь, кажется,со времени, когда Unicode все еще был 16-битным набором символов - в настоящее время он также позволяет символы более 0xFFFF, которые будут представлены двумя значениями Java char каждый (в формате UTF-16, суррогатная пара), и потребуется 4байт в UTF-8, если я правильно рассчитал.Однако я уверен, что реализация здесь - похоже, они просто написаны в формате CESU-8 (например, две 3-байтовые последовательности, каждая из которых соответствует суррогату UTF-16, которые вместе даютодин символ Unicode).Вам также придется позаботиться об этом.

Если вы используете Java, проще всего было бы использовать DataInputStream для чтения этого в строку, а затем преобразовать его (с помощью getBytes("UTF-8") или OutputStreamWriterк реальным данным UTF-8.

1 голос
/ 22 июня 2011

Разница не в Java, только в DataInput/OutputStream.Если строковые данные были записаны с использованием DataOutputStream, просто прочитайте их с использованием DataInputStream.

Если вам нужно записать строковые данные, скажем, в файл, не используйте DataOutputStream, используйтеWriter, который предназначен для символьных потоков.

0 голосов
/ 22 июня 2011

Если у вас возникли проблемы с чтением «сохраненной» строки Java, вам нужно посмотреть в спецификации методов, которые читают / пишут в этом формате:

  • Если строка быланаписанный с использованием DataOutput.writeUTF8, DataInput.readUTF8() javadoc является окончательной спецификацией.В дополнение к нестандартной обработке NUL, она указывает, что строка начинается с 16-разрядного числа байтов без знака.

  • Если строка была записана с использованием ObjectOutputStream.writeObject(), тоспецификация сериализации является окончательной.

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