检测UTF-16文件内容

9

如何判断文件是Unicode(每个字符占16字节)还是8位ASCII码?

8个回答

10

如果文件中存在字节顺序标记(byte-order-mark),则您 可能 能够读取它。


5

UTF-16字符都至少有16位,一些带有正确前缀(0xE000到0xFFFF)的字符是32位。因此,仅仅扫描每个字符以查看是否小于128是行不通的。例如,两个字节0x20 0x20会编码为ASCII和UTF-8中的两个空格,但在UTF-16中编码为单个字符0x2020(匕首)。如果文本已知为英语,偶尔出现非ASCII字符,则几乎每个其他字节都将为零。但是,如果没有关于文本和/或其编码的某些先验知识,则无法可靠地区分普通ASCII字符串和普通UTF-16字符串。


4

关于读取字节顺序标记,就像Brian Agnew所说的那样,有一个特殊的两个字节可能会出现在文件开头。

您还可以通过扫描文件中的每个字节并查看它们是否都小于128来知道它是否为ASCII。如果它们都小于128,则只是一个ASCII文件。如果其中一些大于128,则其中有其他编码。


2
首先,ASCII是7位的,所以如果任何一个字节的高位被设置了,你就知道这个文件不是ASCII。
各种“常见”的字符集,如ISO-8859-x、Windows-1252等,都是8位的,所以如果每隔一个字节为0,你就知道你正在处理只使用ISO-8859字符的Unicode。
当你试图区分Unicode和UTF-8之类的编码时,你会遇到问题。在这种情况下,几乎每个字节都会有一个值,所以你不能轻易地做出决定。正如Pascal所说,你可以对内容进行某种统计分析:阿拉伯语和古希腊语可能不会在同一个文件中出现。然而,这可能比它的价值更多的工作。

根据OP的评论进行编辑:

我认为只需检查您的内容中是否存在0值字节(ASCII NUL),并基于此进行选择,就足够了。原因是JavaScript关键字是ASCII码,而ASCII码是Unicode的子集。因此,这些关键字的任何Unicode表示都将包含一个包含ASCII字符(低位)的字节和另一个包含0(高位)的字节。

我的一个警告是,您仔细阅读文档以确保他们对“Unicode”一词的使用是正确的(我查看了this page以了解该函数,没有进一步查看)。


我需要在本地嵌入(http://code.google.com/p/jslibs)中编译JavaScript文件时,在JS_CompileScript()和JS_CompileUCScript()之间进行选择。 - Franck Freiburger

1
要以编程方式确定文件类型(包括但不限于编码),最好的选择是使用libmagic。它是BSD许可证,是您即将遇到的几乎每个Unix系统的一部分,但对于较小的系统,您可以将其捆绑到应用程序中。
例如,从C中检测mime类型就像这样简单:
Magic = magic_open(MAGIC_MIME|MAGIC_ERROR);

mimetype = magic_buffer(Magic, buf, bufsize);

其他语言有自己的模块包装这个库。
回到你的问题,这是我从file(1)libmagic(3)的命令行界面)得到的:
% file /tmp/*rdp
/tmp/meow.rdp: Little-endian UTF-16 Unicode text, with CRLF, CR line terminators

1
如果你需要解决的文件足够长,并且你有一些想法它应该是什么(比如说,Unicode编码的英文文本或ASCII编码的英文文本),那么你可以对字符进行简单的频率分析,看看分布是否类似于ASCII或Unicode。

1

Unicode是一个字母表,而不是一种编码方式。你可能想说的是UTF-16。有很多库可以自动检测文本的编码方式(比如python-chardet),但它们都使用启发式算法。


2
不幸的是,微软一直将UTF-16LE编码称为“Unicode”,这让问题变得非常混乱。 - bobince
1
Unicode不是一个字母表,而是一种编码方式,它可以编码许多字母表。可以将其视为从字母表到数字形式表示的映射。 - Victor Engel
1
Unicode既不是字母表也不是编码,而是一种编码字符集,提供多种字符编码(UTF-8、UTF-16和UTF-32)。 - Gustaf Liljegren
1
我再次反对一下好吗?它不是像ISO/EIC 10646那样的字母表、编码或编码字符集,而是一种用于编码、处理和表示书写系统的标准。除了字符集之外,Unicode还增加了排序规则、形式规范化以及从右到左的脚本(如阿拉伯语和希伯来语)的双向算法。 https://en.wikipedia.org/wiki/Universal_Coded_Character_Set#Differences_from_Unicode - Victor Engel

0

对于您的特定用例,很容易判断。只需扫描文件,如果找到任何NULL("\0"),它必须是UTF-16。JavaScript必须具有ASCII字符,并且它们由UTF-16中的前导0表示。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接