Java 从PDF中提取文本用于Lucene索引的有效方法
我试图使用ApacheTika从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(
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将根据您的块大小配置简单地批量索引几个文件
解耦在这里是强制性的,因为您应该注意到LuceneIndexWriter
是一个线程安全的类,除了在文件解析级别使用多线程外,您还可以使用多线程来执行更快的索引
希望能有帮助
另外,请注意,Java中的字符串与任何普通对象一样都是垃圾收集的,如果它不是内部对象,谢谢您的详细回答。您认为我需要索引或解析文件的整个内容是正确的。我还实现了线程,以加快速度。我需要检查chunk选项,因为它看起来非常有趣。GC正在触发,清理正在正确执行,但我的实际意图是减少堆使用中的峰值数量。在测试场景中,我的堆使用率高达1GB,但在所有索引过程完成后,实际使用率可能为20MB。我将检查块方法并确认。如果问题解决,将标记此为答案