Преобразование UTF8 в UTF16 с помощью iconv - программирование

Преобразование UTF8 в UTF16 с помощью iconv

Когда я использую 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. Любая помощь по этому поводу?

4b9b3361

Ответ 1

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

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

Если вы находитесь на машине с маленьким контентом, я не вижу способа сказать iconv для генерации big-endian 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

Ответ 2

Сначала я конвертирую в UTF-16, который добавит знак байтового порядка, если необходимо как упоминает Кейт Томпсон. Тогда, поскольку UTF-16 не определяет endianness, мы должны использовать 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

Ответ 3

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

Проблема: Я получил текстовый файл данных от пользователя, и я собирался обработать его на Linux (в частности, Ubuntu) с помощью оболочки script (токенизация, разделение и т.д.). Позвоните в файл 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

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

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

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

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

    myfile.txt: ASCII text, with very long lines
    

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