Почему я не могу преобразовать UTF-8 в MS-ANSI с помощью iconv?

Почему я не могу преобразовать UTF-8 в MS-ANSI с помощью iconv?

Я пытаюсь преобразовать файл из utf-8 в ms-ansi.

я использую

  iconv -f UTF8 -t MS-ANSI// < data.txt

но получить

  iconv: illegal input sequence at position 171359

при рассмотрении этого вопроса

 dd if=data.txt of=error.txt bs=1 count=10 skip=171359

Я понимаю это:

 hexdump -C error.txt
 00000000  ef bb bf 38 3a 6e 61 09  38 3a                    |...8:na.8:|
 0000000a

файл не utf-8, и если нет, что мне следует использовать вместо iconv?

решение1

$ printf '\xef\xbb\xbf' | uconv -x any-name
\N{ZERO WIDTH NO-BREAK SPACE}

Это символ (U+FEFF, закодированный в 3 байтах в UTF-8), который также используется как byte-order-mark. В любом случае, этот символ не найден в MS-ANSI (неправильное название, иногда даваемое windows-1252, надмножеству iso8859-1), поэтому не может быть преобразован в него.

BOM используются (в начале некоторого текста) для различения UTF16-LE от UTF16-BE (или других небайтовых кодировок, на которые влияет порядок байтов ЦП). Это не имеет смысла в UTF-8, где нет неоднозначности порядка байтов, это будет иметь еще меньше смысла в windows-1252, которая является однобайтовой кодировкой символов. Как "пробел нулевой ширины без разрыва", он также невидим и не имеет свойства разделения слов, как символ "пробел нулевой ширины", поэтому, вероятно, его можно безопасно удалить вообще.

С zsh, bashили ksh93:

sed $'s/\ufeff//g' < input | iconv -t windows-1252

В некоторых iconvреализациях вы также можете использовать:

iconv -t windows-1252//translit < input

//translitприбегает к приближениям, когда текст не может быть точно переведен. В этом случае он просто удаляет символ U+FEFF.

$ printf '\xef\xbb\xbf\x38\x3a\x6e\x61\x09\x38\x3a' |
    iconv -t windows-1252//translit | hd
00000000  38 3a 6e 61 09 38 3a                              |8:na.8:|
00000007

Другим вариантом может быть использование:

iconv -t utf-16le | iconv -f utf-16 -t windows-1252

Первый iconvпреобразует в UTF-16 little-endian без BOM, но начальный U+FEFF фактически делает его UTF-16 с BOM, поэтому второй iconvудаляет BOM, поскольку он используется для определения порядка байтов этой utf-16кодировки.

Связанный контент