SVG
文件基本上是XML
文件,所以我可以使用字符串<?xml
(或十六进制表示:'3c 3f 78 6d 6c'
)作为幻数,但有一个没有相反的理由不这样做,例如,如果有额外的空格,它可能会打破这种检查。
我需要/期望检查的其他图像都是二进制文件并且具有幻数。如何在不使用最终使用Python的扩展名的情况下快速检查文件是否为SVG
格式?
答案 0 :(得分:11)
XML不需要以<?xml
前导码开头,因此测试该前缀不是一种好的检测技术 - 更不用说它会将每个XML识别为SVG。一个体面的检测,并且非常容易实现,是使用真正的XML解析器来测试该文件是包含svg
顶级元素的格式良好的XML:
import xml.etree.cElementTree as et
def is_svg(filename):
tag = None
with open(filename, "r") as f:
try:
for event, el in et.iterparse(f, ('start',)):
tag = el.tag
break
except et.ParseError:
pass
return tag == '{http://www.w3.org/2000/svg}svg'
使用cElementTree
确保通过使用expat有效检测; timeit
表示在~200μs内检测到SVG文件,在35μs内检测到非SVG。 iterparse
API使解析器可以放弃创建整个元素树(尽管模块名称),只读取文档的初始部分,无论文件总大小如何。
答案 1 :(得分:2)
您可以尝试将文件的开头读取为二进制文件 - 如果找不到任何幻数,则将其作为文本文件读取,并与您希望的任何文本模式匹配。反之亦然。
答案 2 :(得分:1)
这来自 man file
(here),对于 unix file
命令:
魔术测试用于检查具有特定固定格式数据的文件。典型的例子是二进制可执行文件……这些文件在文件开头附近的特定位置存储了一个“幻数”,告诉 UNIX 操作系统该文件是二进制可执行文件,以及几种类型中的哪一种其中。 “魔法”的概念已通过扩展应用于数据文件。任何在文件中的固定小偏移处具有一些不变标识符的文件通常都可以用这种方式描述。 ...
(我的重点)
这里是 file
命令用来识别 svg
文件 (source) 的“魔法”:
...
0 string \<?xml\ version=
>14 regex ['"\ \t]*[0-9.]+['"\ \t]*
>>19 search/4096 \<svg SVG Scalable Vector Graphics image
...
0 string \<svg SVG Scalable Vector Graphics image
...
如 man magic
所述,每一行都遵循格式 <offset> <type> <test> <message>
。
如果我理解正确,这会查找文字 "<?xml version="
。如果找到,它将查找版本号,如正则表达式所述。如果找到,它将搜索接下来的 4096 个字节,直到找到文字 "<svg"
。如果其中任何一个失败,它会在文件开头查找文字 "<svg"
。
类似的东西可以用 Python 实现。
请注意,还有 python-magic,它提供了 libmagic
的接口,由 unix file
命令使用。