14

SVG文件基本上是一个文件XML,因此我可以使用字符串<?xml(或十六进制表示:)'3c 3f 78 6d 6c'作为幻数,但有一些相反的理由不这样做,例如,如果有额外的空格可能会破坏此检查。

我需要/期望检查的其他图像都是二进制文件并且有幻数。如何在SVG不使用扩展名的情况下快速检查文件是否为格式,最终使用 Python?

4

3 回答 3

15

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'

Using通过使用expatcElementTree确保检测是有效的;显示在约 200μs 内检测到 SVG 文件,在 35μs 内检测到非 SVG。API 使解析器能够放弃创建整个元素树(尽管有模块名称),并且只读取文档的初始部分,而不管总文件大小如何。timeititerparse

于 2013-02-28T13:22:58.493 回答
2

您可以尝试以二进制形式读取文件的开头 - 如果找不到任何幻数,则将其作为文本文件读取并匹配您想要的任何文本模式。或相反亦然。

于 2013-02-28T13:14:18.300 回答
1

这是来自man file(这里),对于 unixfile命令:

魔术测试用于检查具有特定固定格式数据的文件。典型的例子是二进制可执行文件……这些文件有一个“幻数”存储在文件开头附近的特定位置,告诉 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,供 unixfile命令使用。

于 2021-04-06T20:04:55.270 回答