Преобразование 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.
Любая помощь по этому поводу?
Ответы
Ответ 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
или тому подобное. Приветствия.