我正在尝试将文件从 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,以 UTF-8 的 3 个字节编码),也用作字节顺序标记。无论如何,在 MS-ANSI 中都找不到该字符(有时为 windows-1252(iso8859-1 的超集)指定的不正确名称),因此无法转换为该字符。
BOM 用于(在某些文本的开头)区分 UTF16-LE 和 UTF16-BE(或受 CPU 字节序影响的其他非字节编码)。它在没有字节顺序歧义的 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
转换为不带 BOM 的 UTF-16 小端,但初始的 U+FEFF 使其成为带 BOM 的实际 UTF-16,因此第二个iconv
会删除该 BOM,因为它用于确定该编码的字节顺序utf-16
。