Java: объединение 2000-5000 PDF-файлов в 1 с помощью iText приводит к OutOfMemorryError - PullRequest
2 голосов
/ 26 сентября 2011

Я долго смотрел на этот код, пытаясь уменьшить объем памяти, используемый кодом, и все же он генерировал java.lang.OutOfMemoryError: Java heap space.В качестве последнего средства я хочу спросить сообщество, как можно улучшить этот код, чтобы избежать OutOfMemoryError

У меня есть файл драйвера / манифеста (файл .txt), который содержит информацию о файлах PDF.У меня есть около 2000-5000 PDF в ZIP-файл, который мне нужно объединить вместе.Перед объединением, для каждого pdf мне нужно добавить еще 2-3 pdf страницы.Manifest объект содержит информацию о файле PDF.

try{
    blankPdf = new PdfReader(new FileInputStream(config.getBlankPdf()));
    mdxBacker = new PdfReader(new FileInputStream(config.getMdxBacker()));
    theaBacker = new PdfReader(new FileInputStream(config.getTheaBacker()));
    mdxAffidavit = new PdfReader(new FileInputStream(config.getMdxAffidavit()));
    theaAffidavit = new PdfReader(new FileInputStream(config.getTheaAffidavit()));

    ImmutableList<Manifest> manifestList = //Read manifest file and obtain List<Manifest>
    File zipFile = new File(config.getInputDir() + File.separator + zipName);
    //Extracting PDF into `process` folder
    ZipUtil.extractAll(config.getExtractPdfDir(), zipFile);
    outputPdfName = zipName.replace(".zip", ".pdf");
    outputZipStream = new FileOutputStream(config.getOutputDir() + 
                                                    File.separator + outputPdfName);
    document = new Document(PageSize.LETTER, 0, 0, 0, 0);
    writer = new PdfCopy(document , outputZipStream);
    document.open();    //Open the document
    //Start combining PDF files together    
    for(Manifest m : manifestList){
        //Obtain full path to the current pdf
        String pdfFilePath = config.getExtractPdfDir() + File.separator + m.getPdfName();
        //Before combining PDF, add backer and affidavit to individual PDF
        PdfReader pdfReader = PdfUtil.addBackerAndAffidavit(config, pdfType, m, 
                pdfFilePath, blankPdf, mdxBacker, theaBacker, mdxAffidavit, 
            theaAffidavit);
        for(int pageNumber=1; pageNumber<=pdfReader.getNumberOfPages(); pageNumber++){
            document.newPage();
            PdfImportedPage page = writer.getImportedPage(pdfReader, pageNumber);
            writer.addPage(page);
        }
    }
} catch (DocumentException e) {

} catch (IOException e) {

} finally{
    if(document != null) document.close();
    try{
        if(outputZipStream != null) outputZipStream.close();
        if(writer != null) writer.close();
    }catch(IOException e){

    }
}

Пожалуйста, будьте уверены, что я долго смотрю на этот код, и попробуйте переписать его много раз, чтобы уменьшить объем используемой памяти.После OutOfMemoryError по-прежнему остается много файлов pdf, которые не были добавлены на 2-3 дополнительные страницы, поэтому я думаю, что они находятся внутри addBackerAndAffidavit, однако я пытаюсь закрыть все открытые ресурсы, но это все еще исключение.Пожалуйста помоги.

1 Ответ

4 голосов
/ 27 сентября 2011

Вам нужно вызвать PdfWriter#freeReader() к концу каждого цикла, чтобы освободить задействованный PdfReader.PdfCopy#freeReader() имеет этот метод, унаследованный от PdfWriter и делает то же самое.См. Также javadoc :

freeReader

public void freeReader(PdfReader reader)
                throws IOException

Описание, скопированное из класса : PdfWriter
Используйте этот метод для записи читателя в документ и освобождения используемой им памяти.Основное использование - объединение нескольких документов, чтобы ограничить использование памяти текущим добавляемым документом.

Переопределения :
freeReader в классе PdfWriter

Параметры :
reader - PdfReader для освобождения

Броски :
IOException - при ошибке

...