获取PDF中的确切Stringposition

我试图读取一个流,并希望得到每个String的确切位置(坐标)

int size = reader.getXrefSize(); for (int i = 0; i < size; ++i) { PdfObject pdfObject = reader.getPdfObject(i); if ((pdfObject == null) || !pdfObject.isStream()) continue; PdfStream stream = (PdfStream) pdfObject; PdfObject obj = stream.get(PdfName.FILTER); if ((obj != null) && obj.toString().equals(PdfName.FLATEDECODE.toString())) { byte[] codedText = PdfReader.getStreamBytesRaw((PRStream) stream); byte[] text = PdfReader.FlateDecode(codedText); FileOutputStream o = new FileOutputStream(new File("/home..../Text" + i + ".txt")); o.write(text); o.flush(); o.close(); } } 

我实际上得到了这样的位置

 ...... BT 70.9 800.9 Td /F1 14 Tf  Tj 10.1 0 Td  Tj 9.3 0 Td  Tj 3.9 0 Td  Tj 10.1 0 Td  Tj 18.7 0 Td  Tj 21 0 Td  Tj 24.9 0 Td  Tj 10.1 0 Td  Tj 28.8 0 Td  Tj 3.8 0 Td  Tj 8.6 0 Td  Tj 29.5 0 Td  Tj 16.4 0 Td  Tj 7.8 0 Td  Tj 12.4 0 Td  Tj 7.8 0 Td  Tj 3.9 0 Td  Tj 7.8 0 Td  Tj 7.8 0 Td  Tj 3.9 0 Td  Tj 10.8 0 Td  Tj 7.8 0 Td  Tj 10.9 0 Td  Tj ET ..... 

但是我不知道哪个字符串适合哪个位置另一方面在Itext中我可以得到纯文本

 PdfReader reader = new PdfReader(new FileInputStream("/home/....xxx.pdf")); PdfTextExtractor extract = new PdfTextExtractor(reader); 

但当然没有任何立场……

那么我怎样才能得到每个文本的确切位置(字符串,字符,…)?

正如基座和David van Driessche在答案中已经指出的那样,从PDF文件中提取文本并非易事。 幸运的是,iText解析器包中的类为您完成了大部分繁重工作。 您已经从该包中找到了至少一个类PdfTextExtractor,但如果您只对页面的纯文本感兴趣,则此类本质上是一个便利实用程序,用于使用iText的解析器function。 在你的情况下,你必须更强烈地查看该包中的类。

使用iText获取文本提取主题信息的起点是第15.3节解析 iText in Action的第二版 PDF ,特别是示例ParsingHelloWorld.java的方法extractText

 public void extractText(String src, String dest) throws IOException { PrintWriter out = new PrintWriter(new FileOutputStream(dest)); PdfReader reader = new PdfReader(src); RenderListener listener = new MyTextRenderListener(out); PdfContentStreamProcessor processor = new PdfContentStreamProcessor(listener); PdfDictionary pageDic = reader.getPageN(1); PdfDictionary resourcesDic = pageDic.getAsDict(PdfName.RESOURCES); processor.processContent(ContentByteUtils.getContentBytesForPage(reader, 1), resourcesDic); out.flush(); out.close(); } 

它使用了RenderListener实现MyTextRenderListener.java :

 public class MyTextRenderListener implements RenderListener { [...] /** * @see RenderListener#renderText(TextRenderInfo) */ public void renderText(TextRenderInfo renderInfo) { out.print("<"); out.print(renderInfo.getText()); out.print(">"); } } 

虽然此RenderListener实现仅输出文本,但它检查的TextRenderInfo对象提供了更多信息:

 public LineSegment getBaseline(); // the baseline for the text (ie the line that the text 'sits' on) public LineSegment getAscentLine(); // the ascentline for the text (ie the line that represents the topmost extent that a string of the current font could have) public LineSegment getDescentLine(); // the descentline for the text (ie the line that represents the bottom most extent that a string of the current font could have) public float getRise() ; // the rise which represents how far above the nominal baseline the text should be rendered public String getText(); // the text to render public int getTextRenderMode(); // the text render mode public DocumentFont getFont(); // the font public float getSingleSpaceWidth(); // the width, in user space units, of a single space character in the current font public List getCharacterRenderInfos(); // details useful if a listener needs access to the position of each individual glyph in the text render operation 

因此,如果您的RenderListener除了使用getText()检查文本外,还会考虑getBaseline()甚至getAscentLine()getDescentLine(). 你有可能需要的所有坐标。

PS: ParsingHelloWorld.extractText() , PdfReaderContentParser中的代码有一个包装类,它允许您在给定PdfReader reader, int page,RenderListener renderListener:的情况下简单地编写以下RenderListener renderListener:

 PdfReaderContentParser parser = new PdfReaderContentParser(reader); parser.processContent(page, renderListener); 

如果您正在尝试进行文本提取,您应该意识到这绝对是一个非常重要的过程。 您至少必须实现RPN计算机来运行代码并累积转换并执行所有文本运算符。 您需要解释当前页面资源集中的字体指标,您可能需要了解文本编码。

当我使用Acrobat 1.0时,我负责“查找…”命令,其中包含您的问题作为子集。 凭借更丰富的工具和更多的专业知识,需要几个月的时间才能做到正确。

如果您想了解Tj运算符的字节,请查看PDF规范: http : //www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/ PDF32000_2008.pdf

更具体地说 – 见9.4.3节。 要解释该部分 – 必须在用于绘制文本的字体中查找每个字节或多个字节的潜在序列(在您的示例中,字体标识为/ F1)。 通过查找,您将找到此代码所指的实际字符。

另外请记住,您在这里看到这些文本命令的顺序可能根本不会反映自然阅读顺序,因此您必须根据您找到的位置找出实际上这些字符的正确顺序。

另请注意,您的PDF文件可能不包含空格。 由于只需将下一个字符稍微向右移动就可以“伪造”空间,因此某些PDF生成器会省略空格。 但是找到坐标中的间隙可能不是一个单词突破。 例如,它也可能是列的结尾。

这真的非常非常困难 – 特别是如果你想在通用PDF文件上做这件事(而不是只有少数你知道总是来自同一来源的布局)。 我很久以前就为一个名为PitStop Pro的产品编写了一个PDF文本编辑器,它仍然存在(不再隶属于它),这是一个非常难的问题。

如果这是一个选项,请尝试使用现有的库或工具。 这种图书馆或工具当然有商业选择; 我对开源/免费库不熟悉,所以我不能对此发表评论。