Linux 使用命令文件 -i return windows-1252 编码文件的错误值 charset=unknow-8bit
Linux using command file -i return wrong value charset=unknow-8bit for a windows-1252 encoded file
使用 nodejs 和 iconv-lite 在 xml 中创建一个带有字符集 windows-1252 的 http 响应文件,file -i 命令无法将其识别为 windows-1252。
服务器端:
r.header('Content-Disposition', 'attachment; filename=teste.xml');
r.header('Content-Type', 'text/xml; charset=iso8859-1');
r.write(ICONVLITE.encode(`<?xml version="1.0" encoding="windows-1252"?><x>€Àáção</x>`, "win1252")); //euro symbol and portuguese accentuated vogals
r.end();
浏览器下载文件,然后我在 Ubuntu 20.04 LTS:
中检查它
file -i teste.xml
/tmp/teste.xml: text/xml; charset=unknown-8bit
当我使用 gedit 打开它时,强调的 vogal 看起来很好,但欧元符号却没有(从 128 到 159 的所有字符都被弄乱了)。
我签入了 windows 10 虚拟机,一切正常。在 Windows 和 Linux 网络浏览器中,它也显示一切正常。
那么,是不是文件命令的问题?如何在 Linux?
中检查文件的正确字符集
谢谢
编辑
结果文件可以得到 here
第二次编辑
我发现一个错误!代码行:
r.header('Content-Type', 'text/xml; charset=iso8859-1');
必须是:
r.header('Content-Type', 'text/xml; charset=Windows-1252');
了解什么是字符编码很重要。
文本文件实际上只是比特流;或者,由于我们大多同意一个字节中有 8 位,因此是一个字节流。字符编码是一种查找 table(有时是更复杂的算法),用于决定向人类显示该字节流的哪些字符。
例如Windows-1252中编码的字符“€”是位串10000000
。相同的位串在其他编码中将意味着其他事情 - 大多数编码分配 一些 意义给所有 256 个可能的字节。
如果某个软件知道该文件应该被读取为 Windows-1252,它可以查找该编码的映射并显示一个“€”。这就是浏览器显示正确内容的方式:您已经在 Content-Type header 中告诉他们使用 Windows-1252 查找 table.
将文件保存到磁盘后,Content-Type header 中的“Windows-1252”标签不会存储在任何地方。所以任何查看该文件的程序都可以看到它包含位串 10000000
但它不知道要在哪个映射 table 中查找它。你在 HTTP headers 将改变这一点 - none 将影响它在磁盘上的保存方式。
在这种特殊情况下,“文件”命令可以查看XML文档内部的“编码”标记, 并在那里找到“windows-1252”。我的猜测是它根本没有那个功能。因此,它使用其一般逻辑来猜测编码:它可能是 ASCII-compatible,因为它以 ASCII 中拼写 <?xml
的字节开头;但它本身不是 ASCII,因为它的字节超出了 00000000
到 01111111
范围;超出此范围的任何内容都很难猜测,因此输出“unknown-8bit”。
使用 nodejs 和 iconv-lite 在 xml 中创建一个带有字符集 windows-1252 的 http 响应文件,file -i 命令无法将其识别为 windows-1252。
服务器端:
r.header('Content-Disposition', 'attachment; filename=teste.xml');
r.header('Content-Type', 'text/xml; charset=iso8859-1');
r.write(ICONVLITE.encode(`<?xml version="1.0" encoding="windows-1252"?><x>€Àáção</x>`, "win1252")); //euro symbol and portuguese accentuated vogals
r.end();
浏览器下载文件,然后我在 Ubuntu 20.04 LTS:
中检查它file -i teste.xml
/tmp/teste.xml: text/xml; charset=unknown-8bit
当我使用 gedit 打开它时,强调的 vogal 看起来很好,但欧元符号却没有(从 128 到 159 的所有字符都被弄乱了)。
我签入了 windows 10 虚拟机,一切正常。在 Windows 和 Linux 网络浏览器中,它也显示一切正常。
那么,是不是文件命令的问题?如何在 Linux?
中检查文件的正确字符集谢谢
编辑 结果文件可以得到 here
第二次编辑 我发现一个错误!代码行:
r.header('Content-Type', 'text/xml; charset=iso8859-1');
必须是:
r.header('Content-Type', 'text/xml; charset=Windows-1252');
了解什么是字符编码很重要。
文本文件实际上只是比特流;或者,由于我们大多同意一个字节中有 8 位,因此是一个字节流。字符编码是一种查找 table(有时是更复杂的算法),用于决定向人类显示该字节流的哪些字符。
例如Windows-1252中编码的字符“€”是位串10000000
。相同的位串在其他编码中将意味着其他事情 - 大多数编码分配 一些 意义给所有 256 个可能的字节。
如果某个软件知道该文件应该被读取为 Windows-1252,它可以查找该编码的映射并显示一个“€”。这就是浏览器显示正确内容的方式:您已经在 Content-Type header 中告诉他们使用 Windows-1252 查找 table.
将文件保存到磁盘后,Content-Type header 中的“Windows-1252”标签不会存储在任何地方。所以任何查看该文件的程序都可以看到它包含位串 10000000
但它不知道要在哪个映射 table 中查找它。你在 HTTP headers 将改变这一点 - none 将影响它在磁盘上的保存方式。
在这种特殊情况下,“文件”命令可以查看XML文档内部的“编码”标记, 并在那里找到“windows-1252”。我的猜测是它根本没有那个功能。因此,它使用其一般逻辑来猜测编码:它可能是 ASCII-compatible,因为它以 ASCII 中拼写 <?xml
的字节开头;但它本身不是 ASCII,因为它的字节超出了 00000000
到 01111111
范围;超出此范围的任何内容都很难猜测,因此输出“unknown-8bit”。