Конвертировать UTF8 в UTF16 используя iconv - PullRequest
26 голосов
/ 19 января 2012

Когда я использую iconv для преобразования из UTF16 в UTF8, тогда все в порядке, но наоборот, это не работает. У меня есть эти файлы:

a-16.strings:    Little-endian UTF-16 Unicode c program text
a-8.strings:     UTF-8 Unicode c program text, with very long lines

Текст в редакторе выглядит нормально. Когда я запускаю это:

iconv -f UTF-8 -t UTF-16LE a-8.strings > b-16.strings

Тогда я получаю такой результат:

b-16.strings:    data
a-16.strings:    Little-endian UTF-16 Unicode c program text
a-8.strings:     UTF-8 Unicode c program text, with very long lines

Утилита file не показывает ожидаемый формат файла, и текст также не выглядит хорошим в редакторе. Может быть, iconv не создает правильную спецификацию? Я запускаю его в командной строке MAC.

Почему b-16 не в правильном формате UTF-16LE? Есть ли другой способ конвертировать utf8 в utf16?

Более подробно ниже.

$ iconv -f UTF-8 -t UTF-16LE a-8.strings > b-16le-BAD-fromUTF8.strings
$ iconv -f UTF-8 -t UTF-16 a-8.strings > b-16be.strings 
$ iconv -f UTF-16 -t UTF-16LE b-16be.strings > b-16le-BAD-fromUTF16BE.strings

$ file *s
a-16.strings:                   Little-endian UTF-16 Unicode c program text, with very long lines
a-8.strings:                    UTF-8 Unicode c program text, with very long lines
b-16be.strings:                 Big-endian UTF-16 Unicode c program text, with very long lines
b-16le-BAD-fromUTF16BE.strings: data
b-16le-BAD-fromUTF8.strings:    data


$ od -c a-16.strings | head
0000000  377 376   /  \0   *  \0      \0  \f 001   E  \0   S  \0   K  \0

$ od -c a-8.strings | head 
0000000    /   *   *   *       Č  **   E   S   K   Y       (   J   V   O

$ od -c b-16be.strings | head
0000000  376 377  \0   /  \0   *  \0   *  \0   *  \0     001  \f  \0   E

$ od -c b-16le-BAD-fromUTF16BE.strings | head                                
0000000    /  \0   *  \0   *  \0   *  \0      \0  \f 001   E  \0   S  \0

$ od -c b-16le-BAD-fromUTF8.strings | head
0000000    /  \0   *  \0   *  \0   *  \0      \0  \f 001   E  \0   S  \0

Ясно, что спецификация отсутствует, когда я запускаю преобразование в UTF-16LE. Любая помощь в этом?

Ответы [ 3 ]

35 голосов
/ 19 января 2012

UTF-16LE указывает iconv генерировать UTF-16 с прямым порядком байтов без спецификации (метка порядка байтов). Очевидно, предполагается, что, поскольку вы указали LE, спецификация не требуется.

UTF-16 говорит ему генерировать текст UTF-16 (в порядке байтов локального компьютера) с спецификацией.

Если вы работаете на машине с прямым порядком байтов, я не вижу способа iconv сгенерировать UTF-16 с прямым порядком байтов с помощью спецификации, но я могу просто что-то упустить.

Я обнаружил, что команда file не распознает текст UTF-16 без спецификации, и ваш редактор тоже может этого не делать. Но если вы запустите iconv -f UTF-16LE -t UTF_8 b-16 strings, вы должны получить действительную версию UTF-8 исходного файла.

Попробуйте запустить od -c для файлов, чтобы увидеть их фактическое содержимое.

ОБНОВЛЕНИЕ:

Похоже, что вы находитесь на машине с прямым порядком байтов (x86 - с прямым порядком байтов), и вы пытаетесь сгенерировать файл UTF-16 с прямым порядком байтов с помощью спецификации. Это верно? Насколько я могу сказать, iconv не будет делать это напрямую. Но это должно работать:

( printf "\xff\xfe" ; iconv -f utf-8 -t utf-16le UTF-8-FILE ) > UTF-16-FILE

Поведение printf может зависит от настроек вашего языка; У меня LANG=en_US.UTF-8.

(Кто-нибудь может предложить более элегантное решение?)

Еще один обходной путь, , если , то вы знаете, что порядок вывода, производимый -t utf-16:

iconv -f utf-8 -t utf-16 UTF-8-FILE | dd conv=swab 2>/dev/null
3 голосов
/ 27 января 2016

Сначала я преобразую в UTF-16, что, при необходимости, добавит метку порядка байтов , как сказал Кит Томпсон . Тогда, поскольку UTF-16 не определяет порядковый номер, мы должны использовать file, чтобы определить, является ли он UTF-16BE или UTF-16LE. Наконец, мы можем преобразовать в UTF-16LE.

iconv -f utf-8 -t utf-16 UTF-8-FILE > UTF-16-UNKNOWN-ENDIANNESS-FILE
FILE_ENCODING="$( file --brief --mime-encoding UTF-16-UNKNOWN-ENDIANNESS-FILE )"
iconv -f "$FILE_ENCODING" -t UTF-16LE UTF-16-UNKNOWN-ENDIANNESS-FILE > UTF-16-FILE
0 голосов
/ 19 декабря 2012

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

Проблема: Я получил текстовый файл данных от пользователя и собирался обработать его в Linux (в частности, в Ubuntu) с помощью сценария оболочки (токенизация, разбиение и т. Д.). Давайте назовем файл myfile.txt. Первое, что я понял, что что-то не так, было то, что токенизация не работала. Поэтому я не удивился, когда запустил команду file на myfile.txt и получил следующее

$ file myfile.txt

myfile.txt: Little-endian UTF-16 Unicode text, with very long lines, with CRLF line terminators

Если файл был совместимым, вот что должно было быть в беседе:

$ file myfile.txt

myfile.txt: ASCII text, with very long lines

Решение: Чтобы сделать файл данных совместимым, ниже приведены 3 ручных шага, которые, как я обнаружил, сработали после некоторых проб и ошибок с другими шагами.

  1. Сначала преобразуйте в Big Endian в той же кодировке через vi (или vim). vi myfile.txt. В vi сделайте :set fileencoding=UTF-16BE, затем запишите файл. Возможно, вам придется форсировать его с помощью :!wq.

  2. vi myfile.txt (который теперь должен быть в utf-16BE). В vi сделайте :set fileencoding=ASCII, затем запишите файл. Снова, вам, возможно, придется форсировать запись с помощью !wq.

  3. Запустить dos2unix конвертер: d2u myfile.txt. Если вы сейчас запустите file myfile.txt, вы должны увидеть вывод или что-то более знакомое и уверенное, например:

    myfile.txt: ASCII text, with very long lines
    

Вот и все. Это то, что сработало для меня, и я смог запустить скрипт обработки оболочки bash myfile.txt. Я обнаружил, что не могу пропустить шаг 2. То есть в этом случае я не могу перейти непосредственно к шагу 3. Надеюсь, вы найдете эту информацию полезной; надеюсь, кто-то может автоматизировать это, возможно, через sed или тому подобное. Приветствия.

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