在 pdfbox 中使用 PDType0Font 时 PDFTextStripper().getText 出现问题
Problem with PDFTextStripper().getText when using PDType0Font in pdfbox
我最近开始使用 PDType0Font(我们使用了 PDType1Font.HELVETICA 但需要 unicode 支持)并且我在使用 PDPageContentStream 向文件添加行时遇到错误但是 PDFTextStripper.getText 没有得到更新的文件内容。
我正在加载字体:
PDType0Font.load(document, fontFile)
并按如下方式创建 contentStream:
PDPageContentStream(document, pdPage, PDPageContentStream.AppendMode.PREPEND, false)
我将内容添加到 pdf 的函数是:
private fun addTextToContents(contentStream: PDPageContentStream, txtLines: List<String>, x: Float, y: Float, pdfFont: PDFont, fontSize: Float, maxWidth: Float) {
contentStream.beginText()
contentStream.setFont(pdfFont, fontSize)
contentStream.newLineAtOffset(x, y)
txtLines.forEach { txt ->
contentStream.showText(txt)
contentStream.newLineAtOffset(0.0F, -fontSize)
}
contentStream.endText()
contentStream.close()
当我尝试使用 PDFTextStripper.getText 读取文件内容时,我得到的是更改前的文件。
但是,如果我在阅读 PDFTextStripper 之前添加 document.save,它会起作用。
val txt: String = PDFTextStripper().getText(doc) //not working
doc.save(//File)
val txt: String = PDFTextStripper().getText(doc) //working
如果我在
中使用 PDType1Font.HELVETICA
contentStream.setFont(pdfFont, fontSize)
一切正常,没有任何问题,也没有在阅读文本之前保存文档。
我怀疑问题出在 PDPageContentStream.showTextInternal():
中的代码
// Unicode code points to keep when subsetting
if (font.willBeSubset())
{
int offset = 0;
while (offset < text.length())
{
int codePoint = text.codePointAt(offset);
font.addToSubset(codePoint);
offset += Character.charCount(codePoint);
}
}
这是将 PDType0Font 与嵌入子集和 PDType1Font 一起使用时唯一不同的地方。
有人可以帮忙吗?
我做错了什么?
您的问题,尤其是引用的代码,已经暗示了您问题的答案:
当使用将成为子集 (font.willBeSubset() == true
) 的字体时,关联的 PDF 对象在文件被保存之前是未完成的。另一方面,文本提取需要完成的 PDF 对象才能正常工作。因此,不要将文本提取应用到仍在创建中并使用将成为子集的字体的文档。
您将您的用例描述为
for our unit tests, we are adding text (mandatory text for us) to the document and then using PDFTextStripper we are validating that the file has the proper fields.
正如 Tilman 所建议的:然后保存 PDF,然后重新加载会更有意义。那将是一个更现实的测试。不保存就是偷工减料恕我直言。
确实,在单元测试中,您应该首先生成最终的 PDF,因为它将被发送出去(即将其保存到文件系统或内存中),然后重新加载该文件,并仅测试这个重新加载的文档。
我最近开始使用 PDType0Font(我们使用了 PDType1Font.HELVETICA 但需要 unicode 支持)并且我在使用 PDPageContentStream 向文件添加行时遇到错误但是 PDFTextStripper.getText 没有得到更新的文件内容。
我正在加载字体:
PDType0Font.load(document, fontFile)
并按如下方式创建 contentStream:
PDPageContentStream(document, pdPage, PDPageContentStream.AppendMode.PREPEND, false)
我将内容添加到 pdf 的函数是:
private fun addTextToContents(contentStream: PDPageContentStream, txtLines: List<String>, x: Float, y: Float, pdfFont: PDFont, fontSize: Float, maxWidth: Float) {
contentStream.beginText()
contentStream.setFont(pdfFont, fontSize)
contentStream.newLineAtOffset(x, y)
txtLines.forEach { txt ->
contentStream.showText(txt)
contentStream.newLineAtOffset(0.0F, -fontSize)
}
contentStream.endText()
contentStream.close()
当我尝试使用 PDFTextStripper.getText 读取文件内容时,我得到的是更改前的文件。 但是,如果我在阅读 PDFTextStripper 之前添加 document.save,它会起作用。
val txt: String = PDFTextStripper().getText(doc) //not working
doc.save(//File)
val txt: String = PDFTextStripper().getText(doc) //working
如果我在
中使用 PDType1Font.HELVETICAcontentStream.setFont(pdfFont, fontSize)
一切正常,没有任何问题,也没有在阅读文本之前保存文档。
我怀疑问题出在 PDPageContentStream.showTextInternal():
中的代码 // Unicode code points to keep when subsetting
if (font.willBeSubset())
{
int offset = 0;
while (offset < text.length())
{
int codePoint = text.codePointAt(offset);
font.addToSubset(codePoint);
offset += Character.charCount(codePoint);
}
}
这是将 PDType0Font 与嵌入子集和 PDType1Font 一起使用时唯一不同的地方。
有人可以帮忙吗? 我做错了什么?
您的问题,尤其是引用的代码,已经暗示了您问题的答案:
当使用将成为子集 (font.willBeSubset() == true
) 的字体时,关联的 PDF 对象在文件被保存之前是未完成的。另一方面,文本提取需要完成的 PDF 对象才能正常工作。因此,不要将文本提取应用到仍在创建中并使用将成为子集的字体的文档。
您将您的用例描述为
for our unit tests, we are adding text (mandatory text for us) to the document and then using PDFTextStripper we are validating that the file has the proper fields.
正如 Tilman 所建议的:然后保存 PDF,然后重新加载会更有意义。那将是一个更现实的测试。不保存就是偷工减料恕我直言。
确实,在单元测试中,您应该首先生成最终的 PDF,因为它将被发送出去(即将其保存到文件系统或内存中),然后重新加载该文件,并仅测试这个重新加载的文档。