使用pyPdf合并非标准PDF文件
我想把几个PDF文件合并成一个PDF文档。但是,输入的文件似乎不完全符合标准。文件的结束标记后面还有一些额外的信息:
>>
startxref
1994481
%%EOF
%%PPIRoute: 4
显然,这导致pyPdf 给我抛出了一个异常:
pyPdf.utils.PdfReadError: EOF marker not found
现在问题来了:我该怎么办呢?我可以打开每个文件,去掉最后两行,然后再保存,这样再放进pyPdf里。不过,我不是很喜欢这个主意。也许还有更好的办法?
1 个回答
3
我建议把pdf.py脚本中PdfFileReader
类的read()
方法开头的代码从:
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参考文档中第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