Java 从PDF中提取文本用于Lucene索引的有效方法

Java 从PDF中提取文本用于Lucene索引的有效方法,java,lucene,apache-tika,Java,Lucene,Apache Tika,我试图使用ApacheTika从PDF文件中提取文本内容,然后将数据传递给Lucene进行索引 public static String extract(File file) throws IOException, SAXException, TikaException { InputStream input = new FileInputStream(file); ContentHandler handler = new BodyContentHandler(

我试图使用ApacheTika从PDF文件中提取文本内容,然后将数据传递给Lucene进行索引

public static String extract(File file) throws IOException, SAXException, TikaException {

        InputStream input = new FileInputStream(file);
        ContentHandler handler = new BodyContentHandler(-1);
        Metadata metadata = new Metadata();
        new PDFParser().parse(input, handler, metadata, new ParseContext());
        String plainText = handler.toString();
        input.close();
        return plainText;
    }
我的查询与呼叫相关

handler.toString()

现在,我们正在使用多个线程(4到8,用户可以配置)执行提取过程。那么,有没有其他方法可以获取一个流,我们可以将它提供给Lucene以用于索引目的呢。原因是我觉得巨大的弦会推动更大的堆

如果按照以下方式执行,则当前索引为:

doc.add(new TextField(fieldName, ExtractPdf.extract(file), Field.Store.NO));

我们需要提取和索引大约500K个大小从50KB到50MB不等的文档。

我以前没有在Apache Tika上工作过,但您的问题很有趣,所以我四处查看了一下&我不认为调用
toString()
是问题的根本原因

根据我的理解-效率可以通过决定是否始终需要全文来实现,而不管文本大小如何如果只检索N长度的部分正文,则程序逻辑可以正常工作

我非常确信,您将始终需要全文,并且您的程序不会与部分正文一起工作,因此您可以实现所有效率(假设您始终需要全文)是将大字符串分解成块,如第节-所示,使用自定义内容处理程序装饰器将纯文本流化成块。所以内存方面,您的程序应该仍然能够存储如此大的实体,但是您的实体被分为块,这可能会简化您的下游索引过程

您的程序应该按照支持的最大文件大小列出其内存需求,使用这种方法,您不会得到任何缓解。因此,这是一个很早就决定您希望处理多大文件的决定

另一种选择似乎是开发一个过程,在这个过程中,您以增量方式多次解析同一个文件,这也不是很有效(只是建议作为一种可能的方法,不确定在Tika中是否可行)

啊……长篇大论:)

说到以上几点,您还应该注意,您应该尝试解耦文件解析和索引步骤,以便为每个步骤提供不同的调优和配置

您可以使用线程安全阻塞队列编写典型的生产者-消费者模式,也可以使用

使用Spring batch,您的阅读器将负责读取和解析文件,阅读器将把字符串列表传递给处理器,然后将字符串列表传递给writer,writer将根据您的块大小配置简单地批量索引几个文件

解耦在这里是强制性的,因为您应该注意到Lucene
IndexWriter
是一个线程安全的类,除了在文件解析级别使用多线程外,您还可以使用多线程来执行更快的索引

希望能有帮助


另外,请注意,Java中的字符串与任何普通对象一样都是垃圾收集的,如果它不是内部对象,

谢谢您的详细回答。您认为我需要索引或解析文件的整个内容是正确的。我还实现了线程,以加快速度。我需要检查chunk选项,因为它看起来非常有趣。GC正在触发,清理正在正确执行,但我的实际意图是减少堆使用中的峰值数量。在测试场景中,我的堆使用率高达1GB,但在所有索引过程完成后,实际使用率可能为20MB。我将检查块方法并确认。如果问题解决,将标记此为答案