当前位置: 首页 > 面试题库 >

获取PDF中的确切字符串位置

谷梁裕
2023-03-14
问题内容

我试图读取一个流,并希望为每个字符串获取准确的位置(坐标)

    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 <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
.....

但是我不知道哪个字符串适合哪个位置。另一方面,在Itext中,我只能使用

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

但当然根本没有任何位置。

那么,如何获取每个文本(字符串,字符,…)的确切位置?


问题答案:

正如plinth和David van
Driessche在他们的答案中已经指出的那样,从PDF文件中提取文本并非易事。幸运的是,iText解析器包中的类为您完成了大部分繁重的工作。您已经从该程序包中找到至少一个类,PdfTextExtractor,但是如果您仅对页面的纯文本感兴趣,则该类本质上是使用iText的解析器功能的便捷实用程序。在您的情况下,您必须更深入地研究该软件包中的类。

出发点,以获得与iText的文本提取的主题信息是一款15.3 解析PDF文件
的的iText在行动-第2版,特别是该方法extractText的样本ParsingHelloWorld.java:

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 (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

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

PS:
有是在代码的包装类ParsingHelloWorld.extractText(),PdfReaderContentParser,它允许您只需编写以下给出PdfReader reader,int page,RenderListener renderListener:

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


 类似资料:
  • 问题内容: 我试图在问题历史记录中找到问题的答案,但是当他们浏览了几十个我放弃的匹配答案后,它们又回到了一千多个。所以这是我的问题。 我希望能够找到字符串中正好六个数字的第一个序列。给定字符串“一些文本987654321和一些更多的文本123456,以及其他一些文本再次654321和最后的更多文本”,我想找到与123456序列匹配的正则表达式。 我是regex的新手,对它如何工作的简短解释会很有帮

  • 我试着打印出这个字符串长度, 但是它显示100是不正确的。应该是102。我已经在记事本上检查了两次,它显示102。我不知道我错过了什么。

  • 本文向大家介绍Python中的字符串切片(截取字符串)的详解,包括了Python中的字符串切片(截取字符串)的详解的使用技巧和注意事项,需要的朋友参考一下 字符串索引示意图 字符串切片也就是截取字符串,取子串 Python中字符串切片方法 字符串[开始索引:结束索引:步长] 切取字符串为开始索引到结束索引-1内的字符串 步长不指定时步长为1 字符串[开始索引:结束索引] 练习样例 截取2-末尾的字

  • 问题内容: 我需要获取字符串中第一个字母的位置。 遵循一个基本示例。第一个字母是,所以我需要知道的位置,因为我可以使用。 我想用正则表达式得到第一个字母,而不是添加硬编码的字母()。 提前致谢。 问题答案: 如果我正确阅读了Java文档,则说明您正在寻找match对象的方法:

  • 如何在Go中获取字符串的字符数? 例如,如果我有一个字符串“hello”,该方法应该返回5。我看到返回字节数,而不是字符数,因此返回2而不是1,因为在UTF-8中用两个字节编码。