使用iconv将UTF8转换为UTF16

当我使用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 

编辑器中的文本看起来OK。 当我运行这个:

 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不会创build正确的BOM? 我在MAC命令行上运行它。

为什么不是正确的UTF-16LE格式的B – 16? 有没有另一种转换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 / * * * Č ** ESKY ( JVO $ 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时,BOM就会丢失。 任何帮助吗?

Solutions Collecting From Web of "使用iconv将UTF8转换为UTF16"

UTF-16LE告诉iconv生成没有BOM(字节顺序标记)的little-endian UTF-16。 显然,它假定您自从指定了LE ,BOM就没有必要了。

UTF-16告诉它 BOM生成UTF-16文本(以本地机器的字节顺序)。

如果你在一个小端机器上,我没有办法告诉iconv生成带有BOM的big-endian UTF-16,但是我可能会错过一些东西。

我发现file命令不能识别没有BOM的UTF-16文本,而你的编辑器也可能不会。 但是,如果运行iconv -f UTF-16LE -t UTF_8 b-16 strings ,则应该获得原始文件的有效UTF-8版本。

尝试在文件上运行od -c以查看其实际内容。

更新:

它看起来像是在一个big-endian的机器上(x86是little-endian),并且你正试图用BOM生成一个little-endian的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 

我首先转换为UTF-16 ,如果有必要,Keith Thompson提到 , UTF-16将预先给出一个字节顺序标记。 然后由于UTF-16没有定义字节序,我们必须使用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 

这可能不是一个优雅的解决方案,但我发现了一个手动的方式来确保正确的转换我的问题,我相信是类似于这个主题的主题。

问题:我从用户那里得到了一个文本数据文件,然后我将使用shell脚本(标记化,拆分等)在Linux(特别是Ubuntu)上处理它。 我们调用文件myfile.txt 。 第一个迹象表明,我得到的东西是错误的是,标记化不起作用。 所以当我在myfile.txt上运行file命令并得到以下内容时,我并不感到惊讶

 $ 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 

解决方案:为了使数据文件兼容,以下是经过一些试验和其他步骤的错误后,我发现工作的3个手动步骤。

  1. 首先通过vi (或vim )以相同的编码转换为Big Endian。 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 

而已。 这对我来说是myfile.txt ,然后我可以运行myfile.txt处理bash shell脚本。 我发现我不能跳过第2步。也就是说,在这种情况下,我不能直接跳到第3步。希望你能找到这个信息有用; 希望有人可以通过sed或类似的东西来实现自动化。 干杯。