我正在尝试在 j2ee 应用程序中阅读 pdf 文档。
对于网络应用程序,我必须将 pdf 文档存储在磁盘上。为了方便搜索,我想对文档中的文本进行反向索引;如果是 OCR。
使用 PDFbox 库,可以创建一个包含整个 pdf 文件的 pdfDocument 对象。但是,为了保留内存并提高整体性能,我宁愿将文档作为流处理,并一次将一页读入缓冲区。
我想知道是否可以逐页读取包含pdf的文件流,甚至一次读取一行。
我正在尝试在 j2ee 应用程序中阅读 pdf 文档。
对于网络应用程序,我必须将 pdf 文档存储在磁盘上。为了方便搜索,我想对文档中的文本进行反向索引;如果是 OCR。
使用 PDFbox 库,可以创建一个包含整个 pdf 文件的 pdfDocument 对象。但是,为了保留内存并提高整体性能,我宁愿将文档作为流处理,并一次将一页读入缓冲区。
我想知道是否可以逐页读取包含pdf的文件流,甚至一次读取一行。
对于给定的通用 pdf 文档,至少使用 PDFBox,您无法知道一页的结束位置和另一页的开始位置。
如果您关心资源的使用,我建议您将 pdf 文档解析为 COSDocument,使用 .getObjects() 从 COSDocument 中提取解析的对象,这将为您提供 java.util.List。这应该很容易适应您拥有的任何稀缺资源。
请注意,您可以通过 PDFBox API 轻松地将已解析的 pdf 文档转换为 Lucene 索引。
此外,在进入优化领域之前,请确保您确实需要它们。PDFBox 能够毫不费力地在内存中表示相当大的 PDF 文档。
要从 InputStream 解析 PDF 文档,请查看COSDocument类
要编写 lucene 索引,请查看LucenePDFDocument类
对于 COSDocuments 的内存表示,请查看FDFDocument
在 2.0.* 版本中,像这样打开 PDF:
PDDocument doc = PDDocument.load(file, MemoryUsageSetting.setupTempFileOnly());
这会将缓冲内存使用设置为仅使用没有大小限制的临时文件(无主内存)。
这是在这里回答的。
查看PDF Renderer Java 库。我自己试过了,它似乎比 PDFBox 快得多。但是,我还没有尝试获取 OCR 文本。
这是从上面的链接复制的示例,该示例显示了如何将 PDF 页面绘制到图像中:
File file = new File("test.pdf");
RandomAccessFile raf = new RandomAccessFile(file, "r");
FileChannel channel = raf.getChannel();
ByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
PDFFile pdffile = new PDFFile(buf);
// draw the first page to an image
PDFPage page = pdffile.getPage(0);
//get the width and height for the doc at the default zoom
Rectangle rect = new Rectangle(0,0,
(int)page.getBBox().getWidth(),
(int)page.getBBox().getHeight());
//generate the image
Image img = page.getImage(
rect.width, rect.height, //width & height
rect, // clip rect
null, // null for the ImageObserver
true, // fill background with white
true // block until drawing is done
);
我想您可以逐字节地阅读文件以查找分页符。由于可能存在 PDF 格式问题,逐行比较困难。