如何使用头文件签名(幻数)检查文件类型?
How to check type of files using the header file signature (magic numbers)?
通过输入带有扩展名的文件,我的代码成功地从“幻数”中检测到文件的类型。
magic_numbers = {'png': bytes([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]),
'jpg': bytes([0xFF, 0xD8, 0xFF, 0xE0]),
#*********************#
'doc': bytes([0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1]),
'xls': bytes([0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1]),
'ppt': bytes([0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1]),
#*********************#
'docx': bytes([0x50, 0x4B, 0x03, 0x04, 0x14, 0x00, 0x06, 0x00]),
'xlsx': bytes([0x50, 0x4B, 0x03, 0x04, 0x14, 0x00, 0x06, 0x00]),
'pptx': bytes([0x50, 0x4B, 0x03, 0x04, 0x14, 0x00, 0x06, 0x00]),
#*********************#
'pdf': bytes([0x25, 0x50, 0x44, 0x46]),
#*********************#
'dll': bytes([0x4D, 0x5A, 0x90, 0x00]),
'exe': bytes([0x4D, 0x5A]),
}
max_read_size = max(len(m) for m in magic_numbers.values())
with open('file.pdf', 'rb') as fd:
file_head = fd.read(max_read_size)
if file_head.startswith(magic_numbers['pdf']):
print("It's a PDF File")
else:
print("It's not a PDF file")
我想知道如何在不指定这部分代码的情况下修改它,即一旦我生成或输入文件,它会直接显示文件的类型。
if file_head.startswith(magic_numbers['pdf']):
print("It's a PDF File")
else:
print("It's not a PDF file")
希望你能理解我。
你最喜欢只是迭代循环并测试它们。
您也可以通过使用扩展来优化或提供一些错误检查。如果您去掉扩展名并首先检查它,大多数情况下您会成功,如果没有,您可能不想接受“baby.png”作为 xlsx 文件。那将是可疑的,值得犯错。
但是,如果您忽略扩展名,只需循环条目:
for ext in magic_numbers:
if file_head.startswith(magic_numbers[ext]):
print("It's a {} File".format(ext))
您可能想将它放在 return 类型的函数中,这样您就可以 return 类型而不是打印出来。
编辑
由于一些共享幻数,我们需要假设扩展名是正确的,直到我们知道它不是。我将从文件名中提取扩展名。这可以通过 Pathlib
或仅字符串拆分来完成:
ext = filename.rsplit('.', 1)[-1]
那就具体测试一下
if ext in magic_numbers:
if file_head.startswith(magic_numbers[ext]):
return ext
把分机测试放在第一位,所以把它们放在一起:
ext = filename.rsplit('.', 1)[-1]
if ext in magic_numbers:
if file_head.startswith(magic_numbers[ext]):
return ext
for ext in magic_numbers:
if file_head.startswith(magic_numbers[ext]):
return ext
return nil
通过输入带有扩展名的文件,我的代码成功地从“幻数”中检测到文件的类型。
magic_numbers = {'png': bytes([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]),
'jpg': bytes([0xFF, 0xD8, 0xFF, 0xE0]),
#*********************#
'doc': bytes([0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1]),
'xls': bytes([0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1]),
'ppt': bytes([0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1]),
#*********************#
'docx': bytes([0x50, 0x4B, 0x03, 0x04, 0x14, 0x00, 0x06, 0x00]),
'xlsx': bytes([0x50, 0x4B, 0x03, 0x04, 0x14, 0x00, 0x06, 0x00]),
'pptx': bytes([0x50, 0x4B, 0x03, 0x04, 0x14, 0x00, 0x06, 0x00]),
#*********************#
'pdf': bytes([0x25, 0x50, 0x44, 0x46]),
#*********************#
'dll': bytes([0x4D, 0x5A, 0x90, 0x00]),
'exe': bytes([0x4D, 0x5A]),
}
max_read_size = max(len(m) for m in magic_numbers.values())
with open('file.pdf', 'rb') as fd:
file_head = fd.read(max_read_size)
if file_head.startswith(magic_numbers['pdf']):
print("It's a PDF File")
else:
print("It's not a PDF file")
我想知道如何在不指定这部分代码的情况下修改它,即一旦我生成或输入文件,它会直接显示文件的类型。
if file_head.startswith(magic_numbers['pdf']):
print("It's a PDF File")
else:
print("It's not a PDF file")
希望你能理解我。
你最喜欢只是迭代循环并测试它们。
您也可以通过使用扩展来优化或提供一些错误检查。如果您去掉扩展名并首先检查它,大多数情况下您会成功,如果没有,您可能不想接受“baby.png”作为 xlsx 文件。那将是可疑的,值得犯错。
但是,如果您忽略扩展名,只需循环条目:
for ext in magic_numbers:
if file_head.startswith(magic_numbers[ext]):
print("It's a {} File".format(ext))
您可能想将它放在 return 类型的函数中,这样您就可以 return 类型而不是打印出来。
编辑
由于一些共享幻数,我们需要假设扩展名是正确的,直到我们知道它不是。我将从文件名中提取扩展名。这可以通过 Pathlib
或仅字符串拆分来完成:
ext = filename.rsplit('.', 1)[-1]
那就具体测试一下
if ext in magic_numbers:
if file_head.startswith(magic_numbers[ext]):
return ext
把分机测试放在第一位,所以把它们放在一起:
ext = filename.rsplit('.', 1)[-1]
if ext in magic_numbers:
if file_head.startswith(magic_numbers[ext]):
return ext
for ext in magic_numbers:
if file_head.startswith(magic_numbers[ext]):
return ext
return nil