如何用代码识别文件是 *文本文件* 还是 *二进制文件*,只能通过后缀名吗

2019-07-01 15:29:14 +08:00
 daijinming

判断文本文件可以通过文件头,识别出是 UTF\GBK\或是 Unicode 什么的,但如何识别文本文件 还是 二进制文件 该怎么办?

5660 次点击
所在节点    程序员
41 条回复
msg7086
2019-07-01 16:01:31 +08:00
什么叫文本文件,什么叫二进制文件,你先定义一下再问问题好吗?
如果能以文本方式读取的都叫文本文件,那就是上面 @binux 说的,尝试以文本方式打开,不行就不是咯。

如果没有具体定义的话,文本文件也可以称作二进制文件。反正都是二进制、十六进制存在电脑里的。
怎么区分是「你」来决定的。

随便举个例子。
我们平时下载的种子文件,是用一种叫做 BEncode 的编码方式序列化的。
比如一个数字 30,会编码成 i30e,一个字符串 abc 会编码成 3:abc。
[1,'a']编码后就是 li1e1:ae。
你说这算文本文件吗?
但是种子里存的是文件的 hash,虽然编码结构都是文本,但是遇到 hash 的部分就很可能是二进制了。所以种子文件既可以算是文本文件,也可以算是二进制文件,而且并不能「识别」或者「区分」。

包括有些位图文件,如果颜色正好能对应文本的话,一样可以用文本方式读取。

历史上最著名的文本文件与二进制文件探测应用,是 FTP 协议里的传输方法。你可以用 TYPE I 切换成二进制传输,也可以用 TYPE A 切换成文本传输。至于后来人们因为文本文件类型误判而传坏了多少文件这个我就不多提了。
msg7086
2019-07-01 16:05:41 +08:00
最传统的文本文件就是只包括 ASCII 可显示字符,即 0x20-0x7E。所以像中文啊日文啊这些全都不属于传统的文本文件范畴。特别是像 UTF-8 之类的,大幅利用 7bit 以外的区域、大量使用多字节编码的复杂系统,早就已经可以归属于「二进制文件」了。
msg7086
2019-07-01 16:13:21 +08:00
总结一下。
1. 什么是文本文件,什么是二进制文件,需要「你」来定义。
2. 文本文件也是二进制文件。
3. 现在不是文本文件的,以后可能会变成文本文件。

关于 3,一个很常见的例子就是各种文字编码。
上面提了一个 UTF-8,本来是一堆乱码的,但是只要有解码器,就能解码成字。
还有包括 Windows 上很常见的 UTF-16 编码,正是用到了原先被认为只可能在二进制文件中出现的 0x00。
而现在的一些无法被 UTF-16 解码、被你认为是二进制的格式,说不定就会被以后开始普及的 UTF-32 解码呢。
你现在分辨出的二进制格式,很可能等新的解码方式出来以后,就可以被阐释成某种文本文件了。
v2overflow
2019-07-01 16:13:59 +08:00
文本文件就是二进制文件,如果文本规范的话,可以识别,主流的编码都有编码区间
shuax
2019-07-01 16:32:46 +08:00
chardet 一波
hacher
2019-07-01 16:39:34 +08:00
楼主的需求应该是区分文件是否纯 text 文件。只有文件包含'\x00'肯定不是纯文本~~
jinliming2
2019-07-01 17:15:42 +08:00
首先,所有文件都是二进制文件。
我们常说的 UTF-8,GBK 之类的是文本编码,是将人可读的文本,按照特定的编码表转成二进制序列的一种方式,转成二进制序列之后就可以进行存储了。在读取的时候再按照原来的方式还原,就可以得到原始文本了。
一般我们将这种把纯文本以特定编码存储的文件叫做纯文本文件。
所以,纯文本文件有一个重要属性,就是编码。
任何二进制文件都可以当作纯文本文件打开,只不过会显示为人不可读的字符序列,并且也确实都是字符!甚至使用部分编码打开显示的都是认识的字符(文化水平问题)。比如用 GBK 编码打开一张图片看看?你能说这张图片是纯文本文件吗?

也就是说,任何文件都是二进制文件,当你将其赋予一种文本编码后,它就是一个文本文件。
但这个编码不是随便给的,在有些编码里,特定的二进制序列是不会出现的,比如 0x00 几乎不会出现在任意编码规则里。所以,你可以通过猜测的方式去检查文件是否符合某个编码的规则,以此来确定是否为文本文件。
至于要检测多少种编码,就看你的爱好了。甚至你可以自创一个文本编码,这个文本编码里可以出现 0x00,也不是不可以!
Mithril
2019-07-01 17:53:41 +08:00
除非这文件是你自己写的,不然其他全是靠猜。
你如何区分:用文本编辑器打开二进制文件时显示的乱码 和 故意写成乱码的文本文件
就算你用编码范围限定也是会有误杀的,没什么万全的办法。
soy
2019-07-01 18:14:15 +08:00
hx1997
2019-07-01 18:33:48 +08:00
@jinliming2 #24 一般说的“二进制文件”是与“文本文件”对立的,你非要说文本文件也是二进制也没错,但这不是通常的理解方式。你看维基百科: https://en.wikipedia.org/wiki/Binary_file
"A binary file is a computer file that is not a text file."
AX5N
2019-07-01 18:39:33 +08:00
@hx1997 你也说了,是“一般说”,大家都是理解计算机原理的人,还适用于一般这个概念吗?
Mo0o
2019-07-01 18:41:42 +08:00
不是,Linux 下,你把文件的一首歌的后缀名删点,你打开还是以音乐方式播放。
hx1997
2019-07-01 18:43:37 +08:00
@AX5N #28 可以不杠吗? binary file 和 text file 的正常理解就是二元对立的,GNU diff 的手册里也是这么用的: https://www.gnu.org/software/diffutils/manual/html_node/Binary.html
你的意思是 GNU 的人不懂计算机原理吗?
zhangchioulin
2019-07-01 19:37:28 +08:00
“可执行文件”是有“魔数”的。
MeteorCat
2019-07-01 19:39:07 +08:00
mime 判断+1
vkhsyj
2019-07-01 19:48:58 +08:00
后缀是不值得信任的东西,读一段内容看看能否解析成文本呗
azh7138m
2019-07-01 19:49:36 +08:00
@shuax py 的 chardet 判断文本的编码在文本不长(小几百字)的时候成功率非常低,尤其是有各种奇葩编码的时候,都是胡乱判断,everedit 判断都比它准。
sikong31
2019-07-01 20:11:03 +08:00
文件都是二进制,要储存就是 1 和 0,你打开一个文件,指定 rt mode 就按默认编码解码文件,rb 就是直接读取。
对于'文本文件'是什么编码,只有编码的人知道。
zjsxwc
2019-07-01 20:19:54 +08:00
老早就有机构规定了二进制文件标准的,

我之前的 mime type 探查器,正好也涉及,见代码:
https://github.com/zjsxwc/mime-type-sniffer/blob/master/src/MimeTypeSniffer/MimeTypeSniffer.php#L316
marshmallow
2019-07-01 22:36:50 +08:00
unix 的 shell /usr/bin/file,你可以多试试几个文件,看看它都怎么判的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/578971

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX