非正式地,我们大多数人都知道有“二进制”文件(目标文件、图像、电影、可执行文件、专有文档格式等)和“文本”文件(源代码、XML 文件、HTML 文件、电子邮件等)。

一般来说,您需要知道文件的内容才能对其执行任何有用的操作,并且如果编码是“二进制”或“文本”,则形成这种观点,这并不重要。当然,文件只存储数据字节,因此它们都是“二进制”,并且“文本”在不知道编码的情况下没有任何意义。然而,谈论“二进制”和“文本”文件仍然很有用,但为了避免冒犯这种不精确定义的任何人,我将继续使用“吓人”引号。

然而,有多种工具可以处理各种文件,实际上,您希望根据文件是“文本”还是“二进制”来执行不同的操作。一个例子是在控制台上输出数据的任何工具。纯“文本”看起来不错,而且很有用。“二进制”数据会弄乱您的终端,并且通常没有什么用处。GNU grep 在确定是否应该将匹配项输出到控制台时至少使用了这种区别。

那么,问题是,如何判断文件是“文本”还是“二进制”?进一步的限制是,如何在类似 Linux 的文件系统上判断?我不知道任何指示文件“类型”的文件系统元数据,因此问题进一步变成,通过检查文件的内容,如何判断它是“文本”还是“二进制”?为了简单起见,我们将“文本”限制为可在用户控制台上打印的字符。特别是你会如何 实施 这?(我认为这个网站暗示了这一点,但我想一般来说,指出执行此操作的现有代码是有帮助的,我应该指定),我并不是真正追求现有程序可以用来做什么这。

有帮助吗?

解决方案

我公司生产的电子表格软件可以读取多种二进制文件格式和文本文件。

我们首先查看 a 的前几个字节 幻数 我们认识到这一点。如果我们无法识别所读取的任何二进制类型的幻数,那么我们会查看文件的前 2K 字节,看看它是否是一个 UTF-8, UTF-16 或当前编码的文本文件 代码页 主机操作系统的。如果它没有通过这些测试,我们就认为它不是我们可以处理的文件并抛出适当的异常。

其他提示

可以使用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(见注释)。

(大写I)

如果它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 */
    }
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top