Java 获取PDF中的确切字符串位置
我试图读取一条流,希望得到每个字符串的确切位置(坐标) 但当然没有任何立场Java 获取PDF中的确切字符串位置,java,pdf,Java,Pdf,我试图读取一条流,希望得到每个字符串的确切位置(坐标) 但当然没有任何立场 那么,如何才能获得每个文本(字符串、字符等)的确切位置呢 如果您试图进行文本提取,您应该意识到这绝对是一个不平凡的过程。您至少必须实现一台RPN机器来运行代码、累积转换并执行所有文本运算符。您将需要从当前页面资源集中解释字体度量,并且可能需要了解文本编码 当我在Acrobat1.0上工作时,我负责“查找…”命令,该命令将您的问题作为一个子集包含在内。有了更丰富的工具和更多的专业知识,花了几个月的时间才把它做好。如果你想做
那么,如何才能获得每个文本(字符串、字符等)的确切位置呢 如果您试图进行文本提取,您应该意识到这绝对是一个不平凡的过程。您至少必须实现一台RPN机器来运行代码、累积转换并执行所有文本运算符。您将需要从当前页面资源集中解释字体度量,并且可能需要了解文本编码
当我在Acrobat1.0上工作时,我负责“查找…”命令,该命令将您的问题作为一个子集包含在内。有了更丰富的工具和更多的专业知识,花了几个月的时间才把它做好。如果你想做文本提取,你应该意识到这绝对是一个不平凡的过程。您至少必须实现一台RPN机器来运行代码、累积转换并执行所有文本运算符。您将需要从当前页面资源集中解释字体度量,并且可能需要了解文本编码
当我在Acrobat1.0上工作时,我负责“查找…”命令,该命令将您的问题作为一个子集包含在内。有了更丰富的工具和更多的专业知识,我们花了几个月的时间才把它做好。如果您想了解Tj操作符的字节数,请查看PDF规范: 更具体地说,请参见第9.4.3节。为了解释该部分,必须在用于绘制文本的字体中查找每个字节或可能的多个字节序列(在您的示例中,字体标识为/F1)。通过查找,您将找到此代码所指的实际字符 同时请记住,您在此处看到这些文本命令的顺序可能根本不反映自然的阅读顺序,因此您必须根据您找到的位置来确定这些字符的正确顺序 另外请记住,您的PDF文件可能不包含空格,例如。由于只需将下一个字符向右移动一点就可以“伪造”空格,因此一些PDF生成器会忽略空格。但在坐标中找到一个缺口可能不是一个断语。例如,它也可以是列的结尾 这是非常非常困难的-尤其是如果您试图在通用PDF文件上执行此操作(而不是仅针对少数您知道总是来自同一来源的布局)。很久以前,我为一款名为PitStop Pro的产品编写了一个PDF文本编辑器,该产品仍然存在(不再与之关联),这是一个非常困难的问题
如果这是一个选项,请尝试使用现有库或工具。对于这样的库或工具,肯定有商业选择;我对开源/免费库不太熟悉,因此无法对此发表评论。如果您想了解Tj操作符的字节数,请查看PDF规范: 更具体地说,请参见第9.4.3节。为了解释该部分,必须在用于绘制文本的字体中查找每个字节或可能的多个字节序列(在您的示例中,字体标识为/F1)。通过查找,您将找到此代码所指的实际字符 同时请记住,您在此处看到这些文本命令的顺序可能根本不反映自然的阅读顺序,因此您必须根据您找到的位置来确定这些字符的正确顺序 另外请记住,您的PDF文件可能不包含空格,例如。由于只需将下一个字符向右移动一点就可以“伪造”空格,因此一些PDF生成器会忽略空格。但在坐标中找到一个缺口可能不是一个断语。例如,它也可以是列的结尾 这是非常非常困难的-尤其是如果您试图在通用PDF文件上执行此操作(而不是仅针对少数您知道总是来自同一来源的布局)。很久以前,我为一款名为PitStop Pro的产品编写了一个PDF文本编辑器,该产品仍然存在(不再与之关联),这是一个非常困难的问题
如果这是一个选项,请尝试使用现有库或工具。对于这样的库或工具,肯定有商业选择;我对开源/免费图书馆不太熟悉,所以我不能对此发表评论。正如普林斯和大卫·范·德里斯基在他们的回答中所指出的那样,从PDF文件中提取文本是非常重要的。幸运的是,iText解析器包中的类为您完成了大部分繁重的工作。您已经从该包中找到了至少一个类,
pdftextractor,
,但如果您只对页面的纯文本感兴趣,则该类本质上是一个方便实用程序,可用于使用iText的解析器功能。在您的例子中,您必须更仔细地查看该包中的类
使用iText获取文本提取主题信息的起点是第15.3节解析PDF,特别是示例的方法extractText
:
它利用了RenderListener
实现:
因此,如果您的RenderListener
除了使用getText()
检查文本外,还考虑getBaseline()
甚至getAscentLine()
和getDescentLine()。
您拥有可能需要的所有坐标
PS:在ParsingHelloWorld.extractText()
中有一个代码包装类,它允许您在给定的PdfReader读取器、
int页面、和RenderListener RenderListener:
PdfReaderContentParser parser = new PdfReaderContentParser(reader);
parser.processContent(page, renderListener);
正如普林斯和大卫·范·德里希在他们的回答中指出的那样,文本
......
BT
70.9 800.9 Td /F1 14 Tf <01> Tj
10.1 0 Td <02> Tj
9.3 0 Td <03> Tj
3.9 0 Td <01> Tj
10.1 0 Td <0405> Tj
18.7 0 Td <060607> Tj
21 0 Td <08090A07> Tj
24.9 0 Td <05> Tj
10.1 0 Td <0B0C0D> Tj
28.8 0 Td <0E> Tj
3.8 0 Td <0F> Tj
8.6 0 Td <090B1007> Tj
29.5 0 Td <0B11> Tj
16.4 0 Td <12> Tj
7.8 0 Td <1307> Tj
12.4 0 Td <14> Tj
7.8 0 Td <07> Tj
3.9 0 Td <15> Tj
7.8 0 Td <16> Tj
7.8 0 Td <07> Tj
3.9 0 Td <17> Tj
10.8 0 Td <0D> Tj
7.8 0 Td <18> Tj
10.9 0 Td <19> Tj
ET
.....
PdfReader reader = new PdfReader(new FileInputStream("/home/....xxx.pdf"));
PdfTextExtractor extract = new PdfTextExtractor(reader);
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();
}
public class MyTextRenderListener implements RenderListener
{
[...]
/**
* @see RenderListener#renderText(TextRenderInfo)
*/
public void renderText(TextRenderInfo renderInfo) {
out.print("<");
out.print(renderInfo.getText());
out.print(">");
}
}
public LineSegment getBaseline(); // the baseline for the text (i.e. the line that the text 'sits' on)
public LineSegment getAscentLine(); // the ascentline for the text (i.e. the line that represents the topmost extent that a string of the current font could have)
public LineSegment getDescentLine(); // the descentline for the text (i.e. 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<TextRenderInfo> getCharacterRenderInfos(); // details useful if a listener needs access to the position of each individual glyph in the text render operation
PdfReaderContentParser parser = new PdfReaderContentParser(reader);
parser.processContent(page, renderListener);