编辑大PDF时iText7(PDFSweep)抛出OutofMemory错误

时间:2018-10-12 15:01:08

标签: itext

我试图使用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)

1 个答案:

答案 0 :(得分:2)

(完整披露:RegexBasedCleanupStrategy的原始作者)

RegexBasedCleanupStrategy不能这样使用。 您正在创建200个此类的实例,所有这些实例都将遍历文档以查看它们是否可以与正则表达式匹配(逐块)。

为此,他们会将所有块存储在文档中,对它们进行排序,然后在它们上循环。

因此您正在内存中复制文档200倍左右。 那是你的瓶颈。

我的建议:构建更好的正则表达式。 您显然可以将关键字a,b,c等与正则表达式匹配

(a)|(b)|(c)

这只会将文档复制到内存中一次,然后尝试将聚合正则表达式与此文档进行匹配。

它同时具有性能和内存占用优势。