如何识别文件内容为ASCII或二进制

如何将文件内容识别为使用C ++的ASCII或二进制文件?

如果一个文件包含十进制字节9-13,32-126,它可能是一个纯粹的ASCII文本文件。 否则,它不是。 但是,它可能仍然是另一种编码中的文本。

如果上述字节外,文件包含十进制字节128-255,则可能是一个8位或基于ASCII的可变长度编码的文本文件,例如ISO-8859-1,UTF-8或ASCII +中文。 如果不是这样,为了某些目的,你可以在这里停下来,把文件看成是二进制文件。 但是,它仍然可以是16位或32位编码的文本。

如果文件不符合上述约束条件,请检查文件的前2-4个字节以获取字节顺序标记 :

  • 如果前两个字节是hexFE FF ,则该文件暂时为 UTF-16 BE。
  • 如果前两个字节是hexFF FE ,而后面的两个字节不是hex00 00 ,则该文件暂定为 UTF-16 LE。
  • 如果前四个字节是hex00 00 FE FF ,则该文件暂定为 UTF-32 BE。
  • 如果前四个字节是hexFF FE 00 00 ,则该文件暂定为 UTF-32 LE。

如果通过上面的检查,你已经确定了一个暂定的编码,那么只检查下面相应的编码,以确保该文件不是一个恰好与字节顺序标记匹配的二进制文件。

如果您尚未确定暂定编码,则该文件可能仍然是这些编码中的一个文本文件,因为字节顺序标记不是必需的,因此请检查以下列表中的所有编码:

  • 如果文件包含十进制值9-13,32-126和128或更高的大端两字节字,则该文件可能是UTF-16 BE。
  • 如果文件包含十进制值9-13,32-126和128或更高的小尾数两字节字,则该文件可能是UTF-16 LE。
  • 如果文件包含十进制值9-13,32-126和128或更高的大端四字节字,则该文件可能是UTF-32 BE。
  • 如果文件包含十进制值9-13,32-126和128或更高的小端四字节字,则文件可能是UTF-32 LE。

如果在所有这些检查之后,仍然没有确定编码,那么文件就不是我所知道的任何基于ASCII编码的文本文件,因此对于大多数目的,您可能认为它是二进制的(它可能仍然是成为一个非ASCII编码的文本文件,例如EBCDIC,但是我怀疑这远远超出了你所关心的范围)。

使用stream.get()的正常循环遍历它,并检查您读取的字节值是否<= 127 。 有很多方法可以做到这一点:

 int c; std::ifstream a("file.txt"); while((c = a.get()) != EOF && c <= 127) ; if(c == EOF) { /* file is all ASCII */ } 

但是,正如有人提到的,毕竟所有文件都是二进制文件。 另外,还不清楚“ascii”是什么意思。 如果你指的是字符代码,那么的确是这样。 但是,如果你的意思是只有字母数字的价值,你需要另一种方式去。

我的文本编辑器决定是否存在空字节。 在实践中,这个工作得很好:一个没有空字节的二进制文件是非常罕见的。

看看文件命令如何工作; 它有三个策略来确定文件的types:

  • 文件系统testing
  • 魔术数字testing
  • 和语言testing

根据您的平台以及您感兴趣的可能文件,您可以查看其实现,甚至可以调用它。

每个文件的内容都是二进制的。 所以,别无所知,你不能确定。

ASCII是解释的问题。 如果你在文本编辑器中打开一个二进制文件,你明白我的意思。

大多数二进制文件包含一个可以查找的固定标题(每种types),或者可以将文件扩展名作为提示。 如果您希望使用UTF编码的文件,您可以查找字节顺序标记,但它们也是可选的。

除非你更密切地定义你的问题,否则不能有一个确定的答案。

如果问题真的是如何检测ASCII,那么litb的答案是现货。 但是,如果san在知道如何确定文件是否包含文本之后,则问题变得更加复杂。 ASCII只是一种 – 越来越不受欢迎的表示文本的方式。 Unicode系统 – UTF16,UTF32和UTF8越来越受欢迎。 理论上,通过检查前两个字节是否是Unicode字节顺序标记(BOM)0xFEFF(或者如果字节顺序颠倒,则为0xFFFE),可以很容易地进行testing。 但是,由于这两个字节搞砸了Linux系统的许多文件格式,他们不能保证在那里。 此外,二进制文件可能以0xFEFF开始。

寻找0x00的(或其他控制字符)也不会帮助如果该文件是unicode。 如果文件是UFT16,并且文件包含英文文本,则其他字符将是0x00。

如果您知道文本文件将被写入的语言,则可以分析字节并统计确定它是否包含文本。 例如,英文中最常见的字母是E,其后是T.因此,如果文件包含更多的E和T,而不是Z和X,则可能是文本。 当然,这是必要的testing这个ASCII和各种unicodes来确保。

如果这个文件不是用英文写的,或者你想支持多种语言,那么剩下的两个选项就是在Windows上查看文件扩展名,并且检查前四个字节与“magic file”代码的数据库确定文件的types,从而确定它是否包含文本。

那么这取决于你对ASCII的定义。 您可以检查ASCII代码<128的值或您定义的某些字符集(例如'a' – 'z','A' – 'Z','0' – '9'…),并处理文件作为二进制,如果它包含一些其他字符。

您还可以检查常规换行符(0x10或0x13,0x10)来检测文本文件。

要检查,您必须以二进制文件打开文件。 您不能以文本方式打开文件。 ASCII实际上是二进制的一个子集。 之后,你必须检查字节值。 ASCII字节值为0-127,但是0-31是控制字符。 TAB,CR和LF是唯一的通用控制字符。 你不能(可移植地)使用'A'和'Z'; 不能保证那些是ASCII(!)。 如果你需要他们,你必须定义。

 const unsigned char ASCII_A = 0x41; // NOT 'A' const unsigned char ASCII_Z = ASCII_A + 25; 

这个问题真的没有正确或错误的答案,只是复杂的解决scheme,不适用于所有可能的文本文件。

这里有一个关于记事本如何检测ascii文件types的旧文章链接。 这不是完美的,但看到微软如何处理它是有趣的。

Github的linuguist使用charlock holmes来检测二进制文件,然后使用ICU的字符集检测 。

ICU库可用于许多编程语言,包括C和Java。