如何区分“二进制”和“文本”文件?
-
05-09-2019 - |
题
非正式地,我们大多数人都知道有“二进制”文件(目标文件、图像、电影、可执行文件、专有文档格式等)和“文本”文件(源代码、XML 文件、HTML 文件、电子邮件等)。
一般来说,您需要知道文件的内容才能对其执行任何有用的操作,并且如果编码是“二进制”或“文本”,则形成这种观点,这并不重要。当然,文件只存储数据字节,因此它们都是“二进制”,并且“文本”在不知道编码的情况下没有任何意义。然而,谈论“二进制”和“文本”文件仍然很有用,但为了避免冒犯这种不精确定义的任何人,我将继续使用“吓人”引号。
然而,有多种工具可以处理各种文件,实际上,您希望根据文件是“文本”还是“二进制”来执行不同的操作。一个例子是在控制台上输出数据的任何工具。纯“文本”看起来不错,而且很有用。“二进制”数据会弄乱您的终端,并且通常没有什么用处。GNU grep 在确定是否应该将匹配项输出到控制台时至少使用了这种区别。
那么,问题是,如何判断文件是“文本”还是“二进制”?进一步的限制是,如何在类似 Linux 的文件系统上判断?我不知道任何指示文件“类型”的文件系统元数据,因此问题进一步变成,通过检查文件的内容,如何判断它是“文本”还是“二进制”?为了简单起见,我们将“文本”限制为可在用户控制台上打印的字符。特别是你会如何 实施 这?(我认为这个网站暗示了这一点,但我想一般来说,指出执行此操作的现有代码是有帮助的,我应该指定),我并不是真正追求现有程序可以用来做什么这。
其他提示
可以使用file
命令。它做了一堆的文件(man file
)测试,以决定它是否二进制或文本。你可以看一下/如果你需要做的在C借用它的源代码。
file README
README: ASCII English text, with very long lines
file /bin/bash
/bin/bash: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), stripped
可以判定该文件的 MIME类型,提供
file --mime FILENAME
在速记是file -i
在Linux和file -I
在MacOS(见注释)。
如果它text/
开始,它的文本,否则二进制文件。唯一的例外是XML的应用程序。可以通过在所述文件类型的端寻找+xml
匹配那些。
好吧,如果你只是检查整个文件,看看每个字符是可打印与isprint(c)
。它得到稍微复杂的Unicode。
要区分Unicode文本文件, MSDN提供了一些伟大的意见,以什么做。
它的要点是,首先检查最多的前四个字节:
EF BB BF UTF-8
FF FE UTF-16, little endian
FE FF UTF-16, big endian
FF FE 00 00 UTF-32, little endian
00 00 FE FF UTF-32, big-endian
这会告诉你的编码。然后,你想使用iswprint(c)
的字符在文本文件中的其余部分。对于UTF-8和UTF-16,则需要手动解析数据,因为一个单独的字符可以通过字节的可变数量来表示。此外,如果你真的肛门,你需要使用iswprint
的语言环境的变体,如果这是您的平台上。
Perl有一个体面启发式。使用-B
运算符来测试二进制(和它的对面,-T
来测试文本)。这里的壳一个班轮列出文本文件:
$ find . -type f -print0 | perl -0nE 'say if -f and -s _ and -T _'
(注意,如果没有前一美元那些下划线是正确的(RTFM)。)
这是试图分辨使用启发式算法,如检查文件的第一的名词的字节数,看是否这些字节全部有资格作为“文”的大多数程序或没有(即,做他们都属于可打印的ASCII charcters的范围内)。对于更细的distiction总是有类UNIX系统中的“文件”命令。
一个老话题,但也许有人会觉得这非常有用。 如果你有一个脚本来决定,如果事情是一个文件,那么你可以简单地这样做:
if file -i $1 | grep -q text;
then
.
.
fi
这会得到的文件类型,并用无声的grep你可以,如果它决定文本。
要列出的文本文件的名称在当前目录/子目录:
$ grep -rIl ''
二进制文件:
$ grep -rIL ''
要检查特定文件,稍微修改命令:
$ grep -qI '' FILE
然后,退出状态“0”将意味着该文件是一个文本; '1' - 二进制。 可以检查:
$ $回声?
一个简单的检查是如果它已\0
字符。文本文件没有他们。
如前所述* nix的操作系统具有文件命令中这种能力。该命令使用定义了包含许多流行的文件结构中的幻数的配置文件。
这个文件中,称为魔术在历史保存在/ etc,尽管这可能是在/ usr /股上的一些分布。魔术文件定义到该文件中存在的已知值的偏移,然后可以检查这些位置,以确定该文件的类型。
魔文件的结构和描述可以通过咨询相关手册中找到(人魔法)
作为用于实施中,以及可以被内 file.c <发现/ A>本身,但是,其确定其是否是可读文本或不是文件命令的相关部分是以下
/* Make sure we are dealing with ascii text before looking for tokens */
for (i = 0; i < nbytes - 1; i++) {
if (!isascii(buf[i]) ||
(iscntrl(buf[i]) && !isspace(buf[i]) &&
buf[i] != '\b' && buf[i] != '\032' && buf[i] != '\033'
)
)
return 0; /* not all ASCII */
}