【问题标题】:Fastest way to check that a PDF is corrupted (Or just missing EOF) in Ruby?在 Ruby 中检查 PDF 是否已损坏(或只是缺少 EOF)的最快方法?
【发布时间】:2015-03-25 05:46:30
【问题描述】:

我正在寻找一种方法来检查 PDF 是否缺少文件结尾字符。到目前为止,我发现我可以使用 pdf-reader gem 并捕获 MalformedPDFError 异常,或者我当然可以简单地打开整个文件并检查最后一个字符是否是 EOF。我需要处理很多可能很大的 PDF,并且我想加载尽可能少的内存。

注意:我想要检测的所有文件都缺少 EOF 标记,所以我觉得这是一个比检测一般 PDF“损坏”更具体的场景。最好、最快的方法是什么?

【问题讨论】:

    标签: ruby pdf pdf-reader


    【解决方案1】:

    TL;DR

    查找%%EOF,无论有无相关结构,即使您扫描整个大小合理的 PDF 文件,速度也相对较快。但是,如果您将搜索限制在最后 KB 或最后 6 或 7 个字节,如果您只是想验证 %%EOF\n 是 PDF 文件最后一行的唯一内容,则可以提高速度。

    请注意,只有 PDF 文件的完整解析才能告诉您文件是否已损坏,并且只有文件预告片的完整解析才能完全验证预告片是否符合标准。但是,我在下面提供了两个近似值,它们在一般情况下相当准确且相对较快。

    检查文件尾的最后千字节

    这个选项相当快,因为​​它只查看文件的尾部,并使用字符串比较而不是正则表达式匹配。 According to Adobe:

    Acrobat 查看器只要求 %%EOF 标记出现在文件最后 1024 字节的某处。

    因此,以下将通过在该范围内查找文件尾指令来工作:

    def valid_file_trailer? filename
      File.open filename { |f| f.seek -1024, :END; f.read.include? '%%EOF' }
    end
    

    通过正则表达式对文件尾的更严格检查

    但是,ISO standard 既复杂又严格。它部分表示:

    文件的最后一行应仅包含文件结束标记,%%EOF。前两行应按顺序包含关键字 startxref 和解码流中从文件开头到最后一个交叉引用部分中外部参照关键字开头的字节偏移量。 startxref 行之前应该是预告片字典,由关键字预告片和一系列用双尖括号 (>) 括起来的键值对组成(使用 LESS-THAN SIGNs (3Ch) 和 GREATER-THAN标志 (3Eh))。

    如果不实际解析 PDF,您将无法使用正则表达式完全准确地验证这一点,但您可以接近。例如:

    def valid_file_trailer? filename
      pattern = /^startxref\n\d+\n%%EOF\n\z/m
      File.open(filename) { |f| !!(f.read.scrub =~ pattern) }
    end
    

    【讨论】:

    • 你的第一个例子应该是变量应该是 :IO::SEEK_END 而不是 :END def valid_file_trailer?文件名 File.open 文件名 { |f| f.seek -1024, :IO::SEEK_END; f.read.include? '%%EOF' } 结束
    • @icantbecool 你太迂腐了。 IO#seek 清楚地定义了 :END,这对于这个用例来说很少有歧义。但是,如果您发现需要它的边缘情况,您当然应该随意使用完全限定的命名空间。
    • 它对我不起作用,除非我出于某种原因使用了完全限定的命名空间。感谢它帮助我解决问题的答案。
    猜你喜欢
    • 2013-10-08
    • 1970-01-01
    • 2012-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多