python通过文件头判断文件类型

  • Post category:Python

下面我来为您详细讲解“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文件。