我试图自己使用Apache POI和PDFBox,或者在Apache Tika的上下文中,从MASSIVE Microsoft Office和PDF文件中提取和处理纯文本(在某些情况下是数百兆)。此外,我的应用程序是多线程的,因此我将同时解析许多这些大型文件。
在那个规模上,我必须以流方式处理文件。在整个过程中的任何一步都不能将整个文件保存在主内存中。
我见过许多源代码示例,用于通过输入流将文件加载到Tika / POI / PDFBox中。我已经看到很多通过输出流提取纯文本的例子。但是,我已经进行了一些基本的内存分析实验......我还没有找到任何这些库(Tika,POI或PDFBox)的方法,以避免将整个文档加载到主内存中。
在从流中读取和写入流之间,中间显然存在转换步骤...我还没有找到在流式传输基础上执行的方法。我错过了什么,或者这是使用Tika / POI / PDFBox从MS Office或PDF文件中提取文本的已知问题?我可以拥有真正的端到端流媒体,而且在整个过程中没有文件完全加载到主内存中吗?
答案 0 :(得分:3)
首先要确保,如果你关心内存占用,那就是你正在使用TikaInputStream backed by a File,例如改变
InputStream input = new FileInputStream("foo.xls");
类似
InputStream input = TikaInputStream.get(new File("foo.xls"));
如果你真的只有一个InputStream,而不是一个文件,如果可能的话你想要更低的内存选项,强制Tika将它缓冲到临时文件,如
InputStream origInput = getAnInputStream();
TikaInputStream input = TikaInputStream.get(origInput);
input.getFile();
很多但不是所有的解析器都能够利用后备文件并只读取它们需要的内存到内存中,而不是缓冲整个内容,这将有助于
接下来,确保您的ContentHandler在输出之前不会将所有内容缓冲到内存中。在结果文档上执行XPath查找的任何内容都可能不存在,就像任何具有内部StringBuffer或类似内容的内容一样。选择一个更简单的,并确保你设置在他们进来时在某处写出生成的html /文本sax事件
最后,并非所有Tika解析器都支持流处理。有些只通过解析整个文件的结构来工作,然后在找到有趣的位输出。有了这些,使用文件支持的TikaInputStream可能会有所帮助,但不会停止使用相当多的内存。
在能够输出任何内容之前加载+解析大部分/全部文件的一些常见文档解析器包括: