下面我来为您详细讲解“python通过文件头判断文件类型”的完整实例教程。
1. 简介
在很多场景下,我们需要知道某个文件的类型,以做出相应的操作。通常情况下,我们可以通过扩展名来判断文件类型(如.txt
是文本文件,.jpg
是图片文件等等)。但是如果文件没有扩展名,或者扩展名错误,就无法准确判断文件类型了。这时候就需要使用文件头来判断文件类型。
文件头,也叫做魔数(magic number),是文件开头的一段特定的字节序列,用于描述文件的类型。不同类型的文件的文件头是不同的。例如,PNG
图像文件的文件头是89 50 4E 47 0D 0A 1A 0A
,而JPEG
图像文件的文件头是FF D8 FF
。
2. 实现
在Python中,可以使用binascii
模块和字典来实现通过文件头判断文件类型。
2.1 读取文件头并转换为16进制字符串
先定义一个用于读取文件头的函数get_filetype(filename: str)->str
,它使用了Python的内置函数open()
和read()
读取文件头,并且使用binascii
模块的hexlify()
将文件头转换为16进制字符串。其中,filename
表示需要判断类型的文件的文件名,函数返回值为16进制字符串。
import binascii
def get_filetype(filename: str)->str:
with open(filename, "rb") as f:
file_head = f.read(32)
return binascii.hexlify(file_head)
2.2 判断文件类型并返回
定义一个包含各种文件类型的16进制魔数的字典filetype_dict
,其中每个键值对表示对应的文件类型和其对应的魔数。接着还需要使用一个名为judge_filetype
的函数,该函数用于判断文件类型。
judge_filetype
函数接受文件头的16进制字符串file_head
和上一步得到的字典filetype_dict
作为参数。使用hex2int
函数将16进制字符串转换为整数,并和字典中的每个魔数进行比较,若匹配则返回魔数对应的文件类型,否则返回Unknown
,表示没有匹配到对应类型。
def hex2int(string):
string = "0x" + string
return int(string, 16)
def judge_filetype(file_head:str, filetype_dict:dict):
for k, v in filetype_dict.items():
if hex2int(v) == hex2int(file_head[:len(v)]):
return k
return "Unknown"
filetype_dict = {
"JPEG": "FFD8FFE0",
"PNG": "89504E47",
"GIF": "47494638",
# add more file types and corresponding magic numbers if needed
}
2.3 完整代码示例
将上述代码组合起来,就可以得到完整的实现示例:
import binascii
def get_filetype(filename: str)->str:
with open(filename, "rb") as f:
file_head = f.read(32)
return binascii.hexlify(file_head)
def hex2int(string):
string = "0x" + string
return int(string, 16)
def judge_filetype(file_head:str, filetype_dict:dict):
for k, v in filetype_dict.items():
if hex2int(v) == hex2int(file_head[:len(v)]):
return k
return "Unknown"
filetype_dict = {
"JPEG": "FFD8FFE0",
"PNG": "89504E47",
"GIF": "47494638",
# add more file types and corresponding magic numbers if needed
}
filename1 = "example.jpg"
filename2 = "example.png"
file_head1 = get_filetype(filename1)
file_head2 = get_filetype(filename2)
print(judge_filetype(file_head1, filetype_dict))
print(judge_filetype(file_head2, filetype_dict))
运行上面的示例代码,它将输出:
JPEG
PNG
这说明程序可以正确地识别出example.jpg
文件和example.png
文件。
3. 示例说明
下面给出两个具体的示例说明。
示例1: 判断ZIP压缩包
ZIP压缩包的文件头是50 4B 03 04
。现在我们要判断一个文件是否是ZIP压缩包。假设该文件名为example.zip
。
首先需要修改字典filetype_dict
,添加ZIP压缩文件的文件类型和魔数:
filetype_dict = {
"JPEG": "FFD8FFE0",
"PNG": "89504E47",
"GIF": "47494638",
"ZIP": "504B0304"
}
接着就可以使用上述示例代码进行验证了:
filename = "example.zip"
file_head = get_filetype(filename)
print(judge_filetype(file_head, filetype_dict))
输出结果为:
ZIP
这说明该文件确实是一个ZIP压缩包。
示例2:判断XML文件
XML文件的文件头是3C 3F 78 6D 6C
。现在我们要判断一个文件是否是XML文件。假设该文件名为example.xml
。
同样地,需要修改字典filetype_dict
,添加XML文件的文件类型和魔数:
filetype_dict = {
"JPEG": "FFD8FFE0",
"PNG": "89504E47",
"GIF": "47494638",
"ZIP": "504B0304",
"XML": "3C3F786D6C"
}
然后使用上述示例代码验证:
filename = "example.xml"
file_head = get_filetype(filename)
print(judge_filetype(file_head, filetype_dict))
输出结果为:
XML
这说明该文件确实是一个XML文件。