2013-02-03 4 views
1

У меня есть «windows1255» строки с кодировкой, есть ли безопасный способ я могу преобразовать его в «UTF-8»Кодирование вопросы

строки и наоборот?

В общем есть безопасный способ (это означает, данные не будут повреждены), чтобы конвертировать между

кодировок в Java?

 str.getBytes("UTF-8"); 
    new String(str,"UTF-8"); 

Если исходная строка не кодируется как «UTF-8», могут ли данные быть повреждены?

+0

Вы можете посмотреть на это: http://stackoverflow.com/questions/4016671/how-to-parse-a-string-that-is-in -a-different-encoding-from-java – Danyel

ответ

2

Вы не можете иметь объект String в Java, правильно закодированный как что-либо иное, кроме UTF-16, поскольку это единственная кодировка для тех объектов, которые определены спецификацией. Конечно, вы могли бы сделать что-то неприятное, например, положить 1252 значения в char [] и создать из него String, но все сразу пойдет не так.

У вас есть байты, закодированные различными способами, и вы можете преобразовать их в String и из них, используя конструкторы, которые берут Charset, и с getBytes, как в вашем коде.

Таким образом, вы можете выполнять преобразования с использованием строки в качестве промежуточного. Я не знаю, как в JDK сделать прямое преобразование, но промежуточный, вероятно, не слишком дорогостоящий на практике.

О взаимных переключениях - в целом неправда, что вы можете конвертировать между кодированием без потери данных. Только несколько кодировок могут обрабатывать весь спектр символов Unicode (например, семейство UTF, GB18030 и т. Д.), Тогда как многие устаревшие наборы символов кодируют только небольшое подмножество. Вы не можете безопасно обойти эти наборы символов без потери данных, если только вы не уверены, что входные данные попадают в представимый набор.

1

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

Нет смысла кодировать String как UTF-8, а затем декодировать результат как UTF-8. Он не будет оп, в том, что:

(new String(str.getBytes("UTF-8"), "UTF-8")).equals(str) == true; 

Но есть случаи, когда строка абстракция разваливается и выше будет «с потерями» преобразованием. Из-за внутренних данных реализации строка может содержать непарные суррогаты UTF-16, которые не могут быть представлены в UTF-8 (или любое кодирование , в том числе внутреннее кодирование UTF-16 *). Таким образом, они будут потеряны в кодировке, и когда вы декодируете назад, вы получите исходную строку без недействительных непарных суррогатов.

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

Если вы, однако, проистекаете только из-за неправильной интерпретации строки, вы не можете ничего сделать, потому что столько байтов не имеют представления в Windows-1255 и не попали бы в строку.

Если бы это было не так, то вы могли бы полностью восстановить первоначальный намеченную сообщение от:

new String(str.getBytes("Windows-1255"), "UTF-8"); 

* Это на самом деле неправильно Java, чтобы позволить непарные суррогаты существовать в его струнных в первую очередь так как это не действует UTF-16

+0

Ac «String» действительно показывает, что он кодируется UTF-16 конечным пользователям почти через каждый метод, который имеет дело с 'char' или 'Character's. Такие методы, как 'charAt', любой метод, который принимает индекс или длину и т. Д., Показывают, что кодовые единицы' String' являются UTF-16. Это довольно неудачно и, вероятно, является следствием расширения UCS2 до UTF-16 после того, как это поведение в Java уже было формализовано. Если бы UCS2 не был исключен, API были бы чистыми и не подвергали бы суррогатам и т. Д. – BeeOnRope

+0

@BeeOnRope Да, но это будет очевидно только при использовании редко используемых дополнительных плоскостей. Он по-прежнему работает обычно с BMP и без непарных суррогатов (см. Сноску в ответе), что является обычной 99% -ой ситуацией. – Esailija

+0

Уверен, но я предполагаю, что вы пишете код, рассматривающий API так, как он есть на самом деле, и покрывает 100% -ный случай, а не 99% -ый случай и пересекает ваши пальцы, когда персонажи BMP не появляются. Игнорирование это похоже на то, что вы можете игнорировать текст RTL в пользовательских интерфейсах, летнее время, переполнение целого числа и т. Д., Потому что это не происходит более 1% времени. Строка, в основном представляет API UTF-16. В большинстве случаев вы можете рассматривать его как Unicode и избегать его, но я, конечно, не буду писать код таким образом, и я бы никогда не сделал заявление «у него нет никакой кодировки с точки зрения его пользователей» , – BeeOnRope

Смежные вопросы