在Ruby中检查PDF是否已损坏(或者只是缺少EOF)的最快方法?

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

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

TL; DR

即使您扫描整个合理大小的PDF文件,查找%%EOF (包括或不包含相关结构)都相对较快。 但是,如果您将搜索限制为最后一个千字节,则可以获得速度提升,如果您只想validation%%EOF\n是PDF文件最后一行的唯一内容,则可以获得最后的6或7个字节。

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

检查文件预告片的最后一个Kilobyte

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

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

因此,通过查找该范围内的文件预告片指令,以下内容将起作用:

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

通过Regex对文件预告片进行更严格的检查

但是, ISO标准更复杂,更严格。 它部分说:

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

如果没有实际解析PDF,您将无法使用正则表达式以完美的准确度validation这一点,但您可以接近。 例如:

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