我试图使用PDFSweep从PDF中删除一些内容,以下是我的代码的一部分,我正在使用CompositeCleanupStrategy并将RegexBasedCleanupStrategy添加到该策略中:
CompositeCleanupStrategy strategy = new CompositeCleanupStrategy();
for (int i = 0; i < keywordlist.size(); i++) {
String kvalue = keywordlist.get(i);
Loger.getLogger().info("keyword " + i + "=" + kvalue);
strategy.add(new RegexBasedCleanupStrategy(kvalue).setRedactionColor(ColorConstants.GRAY));
}
try {
PdfWriter writer = new PdfWriter(dest);
writer.setCompressionLevel(0);
PdfDocument pdf = new PdfDocument(new PdfReader(src), writer);
// sweep
PdfAutoSweep pdfAutoSweep = new PdfAutoSweep(strategy);
pdfAutoSweep.cleanUp(pdf);
// close the document
pdf.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
当工作量很小时,例如只有一两个,清理工作正常,如果关键字列表中有243个,则PDF大小约为70 MB,我得到以下错误:
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit
exceeded
at java.lang.String.toLowerCase(String.java:2590)
at java.lang.String.toLowerCase(String.java:2670)
at com.itextpdf.io.font.PdfEncodings.convertToString(PdfEncodings.java:287)
at com.itextpdf.kernel.pdf.PdfString.toUnicodeString(PdfString.java:163)
at com.itextpdf.kernel.pdf.canvas.parser.data.TextRenderInfo.getUnscaledBaselineWithOffset(TextRenderInfo.java:425)
at com.itextpdf.kernel.pdf.canvas.parser.data.TextRenderInfo.getBaseline(TextRenderInfo.java:213)
at com.itextpdf.kernel.pdf.canvas.parser.listener.CharacterRenderInfo.<init>(CharacterRenderInfo.java:112)
at com.itextpdf.kernel.pdf.canvas.parser.listener.RegexBasedLocationExtractionStrategy.toCRI(RegexBasedLocationExtractionStrategy.java:156)
at com.itextpdf.kernel.pdf.canvas.parser.listener.RegexBasedLocationExtractionStrategy.eventOccurred(RegexBasedLocationExtractionStrategy.java:135)
at com.itextpdf.pdfcleanup.autosweep.CompositeCleanupStrategy.eventOccurred(CompositeCleanupStrategy.java:115)
at com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor.eventOccurred(PdfCanvasProcessor.java:534)
at com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor.displayPdfString(PdfCanvasProcessor.java:549)
at com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor.access$4700(PdfCanvasProcessor.java:108)
at com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor$ShowTextArrayOperator.invoke(PdfCanvasProcessor.java:617)
at com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor.invokeOperator(PdfCanvasProcessor.java:452)
at com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor.processContent(PdfCanvasProcessor.java:281)
at com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor.processPageContent(PdfCanvasProcessor.java:302)
at com.itextpdf.kernel.pdf.canvas.parser.PdfDocumentContentParser.processContent(PdfDocumentContentParser.java:77)
at com.itextpdf.kernel.pdf.canvas.parser.PdfDocumentContentParser.processContent(PdfDocumentContentParser.java:90)
at com.itextpdf.pdfcleanup.autosweep.PdfAutoSweep.getPdfCleanUpLocations(PdfAutoSweep.java:130)
at com.itextpdf.pdfcleanup.autosweep.PdfAutoSweep.cleanUp(PdfAutoSweep.java:186)
答案 0 :(得分:2)
(完整披露:RegexBasedCleanupStrategy
的原始作者)
RegexBasedCleanupStrategy
不能这样使用。
您正在创建200个此类的实例,所有这些实例都将遍历文档以查看它们是否可以与正则表达式匹配(逐块)。
为此,他们会将所有块存储在文档中,对它们进行排序,然后在它们上循环。
因此您正在内存中复制文档200倍左右。 那是你的瓶颈。
我的建议:构建更好的正则表达式。 您显然可以将关键字a,b,c等与正则表达式匹配
(a)|(b)|(c)
这只会将文档复制到内存中一次,然后尝试将聚合正则表达式与此文档进行匹配。
它同时具有性能和内存占用优势。