Python入门:文件类型判断

来源:互联网 发布:西安软件开发培训 编辑:程序博客网 时间:2024/06/06 03:39

由原文引发的一场思考:
(http://blog.sina.com.cn/s/blog_52ddfea30102wah6.html)
由于原文blog对代码支持的不是很好,不能有效的反映代码结构,所以请看如下代码:

#test.pyimport osdef is_gif(fname):    f = open(fname,'rb')    first4 = tuple(f.read(4))    return first4 == (0x47,0x49,0x46,0x38)print(is_gif(os.listdir(os.getcwd())[2]))

首先

这里需要强调几个地方,由于原博主使用的是python3.*,而我使用的是2.7,所以在部分代码中有所差别,差别点如下:
python3.*

#'rb'与'br'都是正确的>>> f = open(a,'br')>>> f = open(a,'rb')

python2.*

#'rb'是正确的#'br'会报错>>> f = open(file1,'br')Traceback (most recent call last):  File "<input>", line 1, in <module>ValueError: mode string must begin with one of 'r', 'w', 'a' or 'U', not 'br'>>> f = open(file1,'rb')

其次

该代码中忽略了有关read的一个关键特性,每当执行一次read,文件的操作位置就会向后移,也就是说,当执行第二次的时候,文件当前的指向是上一次执行后的结果,所以说,如果缺少了这一行代码,第一次执行可能能得到想要的结果,但之后的执行结果就会不一样,该代码为seek,可参见我的【上一篇文章】
所以正确的代码如下:

import osdef is_gif(fname):    f = open(fname,'rb')    f.seek(0)    first4 = tuple(f.read(4))    return first4 == (0x47,0x49,0x46,0x38)print(is_gif(os.listdir(os.getcwd())[2]))

补充

python字符与ASCII之间的转换函数,也可以在网上查找对应关系
也可以参考我之前的文章【Python字符串】

>>> ord('F')    #是查看单字符中ASCII的10进制对应关系70>>> chr(56)     #是查看ASCII中10进制数字对应的单字符'8'

这个补充内容有什么用呢?可以先把此原文博客中的(0x47,0x49,0x46,0x38)换算成10进制,然后再使用chr找到相应的字符,结果就知道原文代码想做的操作,如:
0x47就是G、0x49就是I、0x46就是F、0x38就是8,其实就是该文件的前几个字符GIF8

再次

当我使用python2.x和python3.x分别对二进制文件进行read操作时,返回的结果都是如下:

>>> print(f.read(20))b'GIF89a\xd0\x00\xd0\x00\x87B\x00+\x19\x06%Z\x85\x90'

所以说,并不需要使用tuple来对文件进行单字符的16进制进行操作,我们只需要直接比对前3-6个字符是不是等于GIF89a就可以判断,文件是不是gif图,改进后的代码如下:

import osfile1 = os.listdir(os.getcwd())[2]def is_gif(fname):    f = open(fname,'rb')    f.seek(0)    #first4 = tuple(f.read(4))    #return first4 == (0x47,0x49,0x46,0x38)    return f.read(5) == 'GIF89'print(is_gif(file1))
0 0