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

2024-02-22

我尝试读取流并希望获得每个字符串的确切位置(坐标)

    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 of iText 实际应用 — 第二版 http://itextpdf.com/book/index.php,特别是方法extractText样本的解析HelloWorld.java http://itextpdf.com/examples/iia.php?id=275:

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 http://itextpdf.com/examples/iia.php?id=282:

public class MyTextRenderListener implements RenderListener
{
    [...]

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

虽然这RenderListener实现仅输出文本,文本渲染信息 http://api.itextpdf.com/itext/com/itextpdf/text/pdf/parser/TextRenderInfo.html它检查的对象提供了更多信息:

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()or evengetAscentLine()andgetDescentLine().您拥有可能需要的所有坐标。

PS:有一个代码的包装类ParsingHelloWorld.extractText(), PdfReader内容解析器 http://api.itextpdf.com/itext/com/itextpdf/text/pdf/parser/PdfReaderContentParser.html,它允许您简单地编写以下给定的内容PdfReader reader, anint page,and aRenderListener renderListener:

PdfReaderContentParser parser = new PdfReaderContentParser(reader);
parser.processContent(page, renderListener);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

获取 PDF 中确切的字符串位置 的相关文章

随机推荐

  • UICollectionView 的 iOS 字母滚动

    我有一个集合视图 显示人物及其姓名的多个图像 并且我已经实现了搜索和排序功能 但是 问题是我也想要按字母顺序排列 但是集合视图没有像这样的委托方法UITableView has NSArray sectionIndexTitlesForTa
  • C++ 编程帮助

    您创建一个程序 显示用户输入的两个数字之间 含 的偶数之和 例如 2 和 7 12 之和 2 4 6 这就是我到目前为止所拥有的 但如果你能让我朝着正确的方向前进 那就会有帮助了 Advanced30 cpp displays the su
  • 如何以编程方式从父进程获取子进程的堆栈跟踪?

    假设我在程序中派生了一个子进程 在某个时候 我暂停子进程kill child SIGSTOP 并想要检查堆栈的内容 有没有办法以编程方式从父进程获取子进程的堆栈跟踪 我知道ptrace是跟踪子进程并检查其内存 寄存器的标准方法 我也知道ba
  • 使用 C/C++ 创建多线程应用程序的最简单方法是什么?

    使用 C C 创建多线程应用程序的最简单方法是什么 不幸的是没有简单的方法 有几个选项 Linux 上的 pthread Windows 上的 win32 api 线程或 boost thread 库
  • 如何在运行时查找已加载的 d3.js 扩展及其版本?

    按照 JavaScript 库的惯例 全局根对象由d3 js https d3js org 有一个自我识别属性 该属性返回 并因此在控制台中调用时输出 所用库的版本 在这种情况下 它是 d3 version Now 从 4 0 版本开始 d
  • Keras 中的 Seq2Seq 双向编码器解码器

    我正在尝试使用 Keras 实现 seq2seq 编码器 解码器 并在编码器上使用双向 lstm 如下所示 from keras layers import LSTM Bidirectional Input Concatenate from
  • 如何使用 html、svg 创建可点击的三角形网格?

    我已经创建了一个三角形网格 如下所示 svg margin left 0px margin right 60px padding 0 div div div div
  • Cocoapods 和 XCode5 集成错误

    在新的 XCode5 中构建我的项目时 我收到以下警告 Pods App 作为 libPods App a 的隐式依赖项被拒绝 因为其架构 i386 不包含所有必需的架构 x86 64 要解决此问题 请选择Pods项目在左侧菜单中 然后在t
  • Firebase 通知在 iOS 11 中不起作用

    我正在开发一个使用 Firebase 推送通知的应用程序 它运行良好 直到我在 iOS 11 中尝试 使用带有 iOS 11 的 iPhone 时 通知不会到达 这是我的代码 void application UIApplication a
  • 从 Eclipse 项目创建多个 JAR

    我已经开始开发一个项目 目前该项目从 Eclipse 项目生成一个整体 JAR 文件 基本上 有一个 Ant 脚本 它会在 Eclipse Java Builder 运行时运行 并获取 Eclipse Java Builder 的输出 cl
  • Spring 的 @DependsOn 不适用于应用程序事件?

    我有一个发送应用程序事件的类 接收者不能错过这个事件 因此发送者依赖于接收者 Service DependsOn receiver class Sender PostConstruct public void init applicatio
  • 一般来说,什么更快,是通过文件进行 grep 还是通过 blob 运行 SQL LIKE %x% 查询?

    假设我正在设计一个工具 可以将代码片段保存在 PostgreSQL MySQL 数据库或文件系统中 我想搜索这些片段 使用像Sphinx这样的搜索引擎似乎不太实用 因为我们在搜索代码时需要代码的精确文本匹配 grep and ack并且一直
  • 如果更新时属性值为 null,则不应将该属性添加到记录中

    假设我有一个像这样的猫鼬模式 var mongoose require mongoose var Schema mongoose Schema var testSchema new Schema name type String requi
  • 如何暂停/延迟我的代码的特定部分

    我在一个类中有一个 PaintComponent 方法 它生成一个 10 10 的网格 我想降低帧速率 以便每次函数为网格中的矩形着色时 我都可以看到进度 public void paint Graphics g1 super paint
  • Ruby 中私有方法应该放在哪里?

    大多数博客或教程或书籍在任何类 模块的底部都有私有方法 这是最佳实践吗 我发现在必要时使用私有方法更方便 例如 public def my method do something minion method end private def
  • Python 正则表达式中的错误? (re.sub 与 re.MULTILINE)

    我注意到 Python 的 Regex 库中有一些奇怪的行为 并且我不确定我是否做错了什么 如果我使用正则表达式对其运行re sub with re MULTILINE 它似乎只替换了前几次出现的情况 如果我关闭它 它会替换所有出现的情况r
  • 有没有办法在python nltk中反转stem?

    我有一个 NLTK python 中的词干列表 并且想要获取创建该词干的可能单词 有没有办法在Python中获取词干并获取词干的单词列表 据我所知 答案是否定的 并且根据词干分析器的不同 可能很难进行详尽的搜索来恢复词干规则的效果 并且无论
  • Zend_Tool:致命错误:无法重新声明类 Zend_Loader

    我能够创建新项目 zf create project ProjectName 但这会创建一个项目而不复制 Zend Framework 库 所以我将 ZF 复制到我的项目库中并尝试创建一个控制器 zf create controller a
  • 当切片索引超出范围时如何引发 IndexError?

    The Python 文档 https docs python org 2 library exceptions html exceptions IndexError指出 切片索引被无声地截断掉在允许范围 因此没有IndexErrors切片
  • 获取 PDF 中确切的字符串位置

    我尝试读取流并希望获得每个字符串的确切位置 坐标 int size reader getXrefSize for int i 0 i lt size i PdfObject pdfObject reader getPdfObject i i