当打开带有utf-16的xml文件时,编辑器显示中文字符

gio*_*ano 0 xml emacs perl utf-8 utf-16

我已经发布了一个xml-utf16问题, 如果我打开xml文件,Emacs会显示中文字符, 但现在我想解读为什么会出现这种问题.也许,如果我有更深入的了解,我可以更好地应对这类问题.

具体来说,我得到了一个用utf16编码的xml文件.我使用emacs(记事本,firefox)从windows xp PC打开文件,显示图(A)(firefox说:格式不正确).显然,该文件是使用utf16编码导出的.(B)显示十六进制版本.(C)使用emacs(revert-buffer-with-coding-system)转换为utf-8后显示xml文件.我还将带有Perl的xml-utf16文件转换为utf8.结果显示在(D)中.

在此输入图像描述

我的问题:

  1. 显然,xml文件是使用utf-16le编码导出的.根据我的理解,utf-16是比utf-8更简单,更旧的编码.为什么utf-8不理解这种编码?为什么编辑会显示汉字?
  2. 如果我想阅读xml文件的内容,建议使用emacs进行转换.由于"@",我得到的是不可读的(C).我认为编码问题是一个常见的任务,像emacs这样的编辑可以应对.我错了还是这个问题(插入"@")由于xml文件的规范错误?为什么字符之间的十六进制版本有一点?
  3. 我从互联网上下载了一个将utf16转换为utf8的Perl代码.如果我将原始的xml文件转换为utf-8,我得到了数字(D).好消息是firefox显示新xml文件的树结构.使用emacs(D)不是这种情况.整个内容写在一行(第一行除外).实际上,原始文件不包含CR或LF.如果我想看看考虑树结构的utf16/utf8 xml文件,那么编写Perl或Python代码似乎是我的工作,它通过插入CR/LF或使用适当的Perl来考虑树结构/ Python-package,不是吗?
  4. 为什么导出数据并生成正在研究的xml文件的导出器在编辑器打开时不考虑LF/CR获取可读的xml文件?这是为了避免大文件大小?
  5. 有关utf16的争论(https://softwareengineering.stackexchange.com/questions/102205/should-utf-16-be-considered-harmful).使用utf16显然存在问题,这个问题大约在4年前被问到.为什么程序员仍然使用utf16?我错过了什么吗?(我想建议我的数据传递者使用utf8).

谢谢你的耐心等待.

ike*_*ami 5

为什么utf-8不理解这种编码?

是吧?UTF-8是一种编码.它不懂编码.你的编辑器是理解编码的,它对UTF-8,UTF-16le和UTF-16be的理解不一定相关.

为什么编辑会显示汉字?

(A)中的问题是您的编辑器使用UTF-16be来解码使用UTF-16le编码的文档.

我错了还是这个问题(插入"@")由于xml文件的规范错误?

该文件是正确的.该文件使用UTF-16le.它指定它使用UTF-16le encoding="utf-16"和BOM.

(C)中的问题是您的编辑器使用单字节编码来解码使用UTF-16le编码的文档.^@代表一个NUL.

为什么字符之间的十六进制版本有一点?

没有.最右边的列显示使用US-ASCII解码的文件的内容,这显然不是.

如果我想看一下考虑树结构的utf16/utf8 xml文件

...然后你需要一个XML查看器/编辑器,它以该形式显示XML,而不是文本编辑器.

为什么导出数据并生成正在研究的xml文件的导出器在编辑器打开时不考虑LF/CR获取可读的xml文件?

简单.

有关utf16的辩论

完全相同的问题发生在UTF-8级别,因为人们没有正确处理字形.如果你正确处理字形,UTF-16的"问题"就会消失.

因此,拒绝UTF-16是因为它是一种可变宽度编码而很少有人认为它对我来说没有意义,因为它对于UTF-8来说是相同的.

为什么程序员仍然使用utf16?我错过了什么吗?

这是Windows内部使用的.

我想建议我的数据传递者使用utf8

对于您在emacs中错误地使用UTF-16be而不是UTF-16le而言,这似乎是一个相当激烈的解决方案.


amo*_*mon 5

你似乎不知道有各种各样的事情:

  • 什么是角色,什么是编码?
  • 什么是Unicode?
  • 什么是各种Unicode编码,它们如何区别,它们的优点和缺点是什么,它们的历史是什么?
  • XML规范对编码有什么看法?
  • 各种操作系统如何与编码相互作用?
  • 如何以可视方式表示二进制数据?
  • XML中的空格有什么作用?
  • ...

基本

这只是Joel Spolsky的"绝对最低限度,每个软件开发人员绝对必须知道关于Unicode和字符集(没有借口!)"的链接.

TL; DR:编码是双射部分函数,​​它将字节序列映射到字符序列并再次返回.Unicode是一个很大的字符列表,每个字符都有一个数字(代码点).各种编码用于将这些代码点映射到字节:

  • ASCII,只能代表128个不同的字符.
  • UTF-16,每个代码点使用至少两个字节.这可以包括空字节.这种编码是模糊的:读取的字节在哪个方向?字节顺序标记0xFEFF0xFFFE排序,其中一个在每个UTF-16文档之前.
  • UTF-8为每个字符使用至少一个字节,并且具有ASCII是UTF-8的子集的属性.它不能包含空字节(好吧,除了实际的NUL).这种编码的缺点是非常高的代码点具有大的表示.与UTF-8相比,UTF-16中的CJK文本可以用更少的字节表示.对于西方文本,它是相反的.

二进制数据的可视化表示

某些字符("控制字符")没有可打印的解释.在你的hexdump中,不可打印的字节用a表示..Emacs和Vim遵循传统的控制代码前缀路由^,这意味着它与下一个字符一起代表控制代码.^@表示NUL字符,^H表示退格,^D表示传输的结束.通过0x40从可视化表示中的ASCII字符中减去,可以获得控制字符的ASCII值.\377是八进制表示0xFF.

XML和编码

XML的默认编码是UTF-8,因为它向后兼容ASCII.使用任何其他编码是不必要的痛苦,正如这个问题所证明的那样.总之,UTF-16 可以被使用,如果正确申报(您输入尝试它),但后来被搞砸.

您输入的问题.

您的文件包含以下部分:

  • BOM 0xFFFE,这意味着第一个字节是输入中的低字节.然后是ASCII字符后跟一个NUL字节.
  • 输入的第一行(在hexdump中最多为0x52字节)包含正确编码的XML声明.
  • 然后,发生了一些不好的事情:我们得到了序列0d00 0d0a.0d00CR,回车.第二部分意味着0a00,换行.它们一起构成了Windows系列的结尾.这0d0a将是一个ASCII CRLF.但这是错误的,因为UTF-16是一个双字节编码.
  • 之后,UTF-16继续,但现在NUL在每个角色之前:另一个UTF-16版本!但你的编辑不知道这一点,并给你美丽的汉字.

发生了什么:

  1. 有人打印出以UTF-16le编码的XML前导码.将\n在年底被自动翻译成\r\n.所以0d00 0a00成了0d00 0d0a 00.

    当您不解码输入时,可能会在Perl中发生这种情况,但会对输出进行编码.在Windows上,Pe​​rl会自动进行换行,这可以通过以下方式关闭binmode $fh.

  2. 文档的其余部分打印在一行中,因此没有进一步的翻译.因为单个字节的添加改变了一切,所以解释发生了巨大的变化.

如果你的脚本能解决这个错误,那么它做反向同样的错误(翻译\r\n\n,并随后对其进行解码).

通过直接解码所有输入并在打印之前再次对其进行编码,可以避免此类错误.在内部,始终对代码点进行操作,而不是字节.在Perl中,编码可以添加到文件句柄中binmode,它可以透明地执行解码和编码.