2012-01-19 3 views
22

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

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. Любая помощь по этому вопросу?

+0

Что делать, если вы использовали 'iconv -f UTF-8 -t UTF-16LE a-8.strings -o b-16.strings' вместо этого? Я сомневаюсь, что это исправит, но это стоит того. – cha0site

+0

Моя версия iconv не поддерживает параметр -o (MacOS). Как вы сказали, это, вероятно, не поможет. Спасибо за попытку в любом случае. –

+0

На вашем выходе отображается значок 'iconv -f UTF-8 -t UTF-16 a-8.strings' (работает в системе little-endian), генерируя широкоугольный UTF-16 с спецификацией. Можете ли вы это подтвердить? Работает ли команда Mac OS 'iconv' иначе, чем в Linux? 'echo hello | iconv -f ascii -t UTF-16 | od -x' –

ответ

31

UTF-16LE говорит iconv генерировать прямой порядок байтов UTF-16 без спецификации (Byte Order Mark). По-видимому, он предполагает, что, поскольку вы указали 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 по файлам, чтобы просмотреть их фактическое содержание.

UPDATE:

Похоже, что вы находитесь на большой обратный порядок байт машины (x86 является прямой порядок байтов), и вы пытаетесь генерировать мало-Endian UTF-16 файл с BOM , Это верно? Насколько я могу судить, 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 
+0

Спасибо Keith за помощью. Я отредактировал свой оригинальный вопрос с большим количеством результатов на основе вашей помощи. Знаете ли вы, как это исправить? Что делать, если я просто вставляю спецификацию там вручную? –

+0

См. Обновленный ответ. –

+0

Я тоже на компьютере на базе Intel, но работает MacOS. Тем не менее ручное добавление спецификации, как вы предлагали, отлично работает. Большое спасибо! –

0

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

Проблема: Я получил текстовый файл от пользователя, и я собирался обработать его на 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 

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

  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 или тому подобное. Приветствия.

3

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