iText 抛出 ClassCastException:PdfNumber 无法转换为 PdfLiteral

Posted

技术标签:

【中文标题】iText 抛出 ClassCastException:PdfNumber 无法转换为 PdfLiteral【英文标题】:iText throws ClassCastException: PdfNumber cannot be cast to PdfLiteral 【发布时间】:2014-10-15 14:03:11 【问题描述】:

我正在使用 iText v5.5.1 读取 PDF 并从中渲染文本:

pdfReader = new PdfReader(new CloseShieldInputStream(is));
pdfParser = new PdfReaderContentParser(pdfReader);

int maxPageNumber = pdfReader.getNumberOfPages();
int pageNumber = 1;

StringBuilder sb = new StringBuilder();

SimpleTextExtractionStrategy extractionStrategy = new SimpleTextExtractionStrategy();

while (pageNumber <= maxPageNumber) 
    pdfParser.processContent(pageNumber, extractionStrategy);

    sb.append(extractionStrategy.getText());

    pageNumber++;

one PDF file 抛出以下异常:

java.lang.ClassCastException: com.itextpdf.text.pdf.PdfNumber cannot be cast to com.itextpdf.text.pdf.PdfLiteral
    at com.itextpdf.text.pdf.parser.PdfContentStreamProcessor.processContent(PdfContentStreamProcessor.java:382)
    at com.itextpdf.text.pdf.parser.PdfReaderContentParser.processContent(PdfReaderContentParser.java:80)

该 PDF 文件似乎已损坏,但它的内容可能仍然有意义...

【问题讨论】:

该 PDF 文件中应该有任何可见的内容吗? 【参考方案1】:

确实

那个 PDF 文件好像坏了

所有页面的内容流是这样的:

/GS1 gs
q
595.00 0 0 

看起来他们都被提前切断了,因为最后一行不是完整的操作。这当然可以像 iText 一样使解析器中断。

此外,内容应该更长,因为即使它们的压缩流的大小也比这个长度大一点。这表明流在字节级别中断。

查看 PDF 文件的字节不禁会注意到

    即使在二进制流中,代码 13 和 10 也只能一起出现,并且 交叉参考偏移值小于实际位置。

因此,我假设此 PDF 已使用将其作为文本数据处理的传输方法进行传输,尤其是用现在在文件中无处不在的 CR LF(CR =回车 = 13;LF = 换行 = 10)。此类替换将自动破坏任何压缩数据流,例如文件中的内容流。

不幸的是……

但也许它的内容仍然有意义

不多。每个页面分别关联一个大图像。考虑到内容流的小尺寸和大图像尺寸,我假设 PDF 仅包含扫描的页面。但是由于上面提到的替换,图像也被破坏了。

【讨论】:

您关于 CR/LF 更换的建议非常好,谢谢。如果您已经知道什么是偏移量,也许您可​​以提供治疗方法?至少也许你可以告诉我在哪里提取这些偏移量以及它们应该具有什么值,以便我可以进一步试验 CR←→LF 转换。似乎该文件需要非常简单的操作(删除 CR 或删除 LF)。 似乎文件需要非常简单的操作(删除 CR 或删除 LF)。 - cr 和 lf 的东西是 明显的 缺陷但存在也可能是其他缺陷。因此,用 cr 或 lf 替换每个 crlf 可能无法修复整个文档。而且你不知道之前每个 crlf 是什么,它可能是一个 cr、一个 lf 或一个 crlf。测试每个变体将意味着尝试非常非常多的变体。 你是对的。我尝试了天真的 crlf→cr 和一次 crlf→lf 但仍然无法打开 PDF。感谢您的建议。【参考方案2】:

这不是最佳解决方案,但我遇到了这个确切的问题,很遗憾无法分享我遇到问题的确切 PDF。

我制作了一个 itextpdf 的分支,它捕获了 ClassCastException 并跳过了它所遇到的问题的 PdfObjects。它打印到 System.out 文本包含什么以及 itextpdf 认为它是什么类型。我无法将其映射到我的 PDF 的一些系统性问题(比我更聪明的人需要这样做),而且这种异常只会在蓝月亮中发生一次。无论如何,如果它对任何人有帮助,这个 fork 至少不会使您的代码崩溃,让您解析大部分 PDF,并为您提供一些关于哪些类型的字节串似乎让 itextpdf 消化不良的信息。

https://github.com/njhwang/itextpdf

【讨论】:

以上是关于iText 抛出 ClassCastException:PdfNumber 无法转换为 PdfLiteral的主要内容,如果未能解决你的问题,请参考以下文章

利用itext生成pdf的简单例子

如何运用Java组件itext生成pdf

如何运用Java组件itext生成pdf

为何选择iText?java PDF开源库选择与iText发展历史

java itext 创建pdf,直接返回输出流做成下载,怎么做

iText学习之路iText in Action 第一章 随便画画带你入门