我想将几个PDF文件合并为一个PDF文档。事实证明,输入文件不完全符合标准。 EOF标记后面是一些其他信息:

>>
startxref
1994481
%%EOF

%%PPIRoute: 4


显然,这会导致pyPdf giving me an exception

pyPdf.utils.PdfReadError: EOF marker not found


现在的问题是:我该怎么办?我可能可以打开每个文件,剥离最后两行并保存,然后再将它们放入pyPdf中。但是,我不太喜欢这个主意。也许那里有更好的选择?

最佳答案

我建议将pdf.py脚本中read()类的PdfFileReader方法的开头更改为:

    def read(self, stream):
        # start at the end:
        stream.seek(-1, 2)
        line = ''
        while not line:
            line = self.readNextEndLine(stream)
        if line[:5] != "%%EOF":
            raise utils.PdfReadError, "EOF marker not found"

    ... etc


至:

    def read(self, stream):
        # start at the end:
        stream.seek(-1, 2)
        line = ''
        # read stream backwards while watching for end-of-file marker
        while line[:5] != "%%EOF":
            line = self.readNextEndLine(stream)

    ... etc


在我看来,原始代码并没有真正做到Adobe PDF 1.3 Reference文档中第3.4.4节“文件尾随”(第628页)所隐含的含义(斜体字):


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


换句话说,在"%%EOF"标记之后文件的物理末尾还有其他内容是可以的。我提出的更改试图适应这种情况,并使其忽略标记后在文件末尾可能附加的所有其他内容,而不是引发异常(但是,不需要"%%EOF"位于最后1K中规范中指出的字节数,尽管可以添加对此的检查)。这也意味着您要合并的文件实际上可能符合规范。

更新:

这是一个版本,还要求"%%EOF"标记位于最后1024个字节内:

def read(self, stream):
    # start at the end
    stream.seek(-1, os.SEEK_END)
    last1K = stream.tell() - 1024 + 1 # offset of last 1024 bytes of stream

    # read stream backwards while watching for end-of-file marker
    line = ''
    while line[:5] != "%%EOF":
        line = self.readNextEndLine(stream)
        if stream.tell() < last1K:
            raise utils.PdfReadError, "EOF marker not found"

    ... etc

09-30 17:46
查看更多