当前位置: 首页 > 知识库问答 >
问题:

Apache PDFBOX-使用split(PDDocument文档)时获取java.lang.OutOfMemoryError

籍兴文
2023-03-14

我正在尝试使用Apache PDFBOX API V2.0.2拆分一个有300页的文档。同时尝试使用以下代码将pdf文件拆分为单页:

        PDDocument document = PDDocument.load(inputFile);
        Splitter splitter = new Splitter();
        List<PDDocument> splittedDocuments = splitter.split(document); //Exception happens here

我收到以下异常

Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded

这表明GC花费了很多时间来清除回收量不合理的堆。

有很多JVM调优方法可以解决这种情况,但是,所有这些都只是治疗症状,而不是真正的问题。

编辑:

这不是http://stackoverflow.com/questions/37771252/splitting-a-pdf-results-in-very-large-pdf-documents-with-pdfbox-2-0-2的重复问题:

 1. I do not have the size problem mentioned in the aforementioned
    topic. I am slicing a 270 pages 13.8MB PDF file and after slicing
    the size of each slice is an average of 80KB with total size of
    30.7MB.
 2. The Split throws the exception even before it returns the splitted parts.

我发现拆分可以通过,只要我不是通过整个文档,而是我通过它作为“批”,每批20-30页,这就完成了工作。

共有1个答案

姜永贞
2023-03-14

PDF Box将拆分操作产生的部分作为PDDocument类型的对象存储在堆中作为对象,这会导致堆快速填充,即使在循环的每一轮之后调用close()操作,GC仍然不能以填充的方式回收堆大小。

一个选项是将文档拆分操作拆分为批,其中每个批是一个相对可管理的块(10到40页)

public void execute() {
    File inputFile = new File(path/to/the/file.pdf);
    PDDocument document = null;
    try {
        document = PDDocument.load(inputFile);

        int start = 1;
        int end = 1;
        int batchSize = 50;
        int finalBatchSize = document.getNumberOfPages() % batchSize;
        int noOfBatches = document.getNumberOfPages() / batchSize;
        for (int i = 1; i <= noOfBatches; i++) {
            start = end;
            end = start + batchSize;
            System.out.println("Batch: " + i + " start: " + start + " end: " + end);
            split(document, start, end);
        }
        // handling the remaining
        start = end;
        end += finalBatchSize;
        System.out.println("Final Batch  start: " + start + " end: " + end);
        split(document, start, end);

    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        //close the document
    }
}

private void split(PDDocument document, int start, int end) throws IOException {
    List<File> fileList = new ArrayList<File>();
    Splitter splitter = new Splitter();
    splitter.setStartPage(start);
    splitter.setEndPage(end);
    List<PDDocument> splittedDocuments = splitter.split(document);
    String outputPath = Config.INSTANCE.getProperty("outputPath");
    PDFTextStripper stripper = new PDFTextStripper();

    for (int index = 0; index < splittedDocuments.size(); index++) {
        String pdfFullPath = document.getDocumentInformation().getTitle() + index + start+ ".pdf";
        PDDocument splittedDocument = splittedDocuments.get(index);

        splittedDocument.save(pdfFullPath);
    }
}
 类似资料:
  • 问题内容: 我正在尝试使用Apache PDFBOX API V2.0.2拆分300页的文档。尝试使用以下代码将pdf文件拆分为单个页面时: 我收到以下异常 这表明GC需要花费大量时间来清除没有被回收量证明合理的堆。 有许多JVM调优方法可以解决这种情况,但是,所有这些方法都只是在解决症状而不是真正的问题。 最后一点,我正在使用JDK6,因此在我的情况下,不能使用新的Java 8 Consumer

  • 问题内容: 我目前从Python开始,我有很强的PHP背景,在PHP中,我习惯于用作文档模板。 我想知道它是否在Python文档中占有一席之地。 这里有哪些既定的公约和/或官方指南? 例如,类似这样的内容太复杂而无法适应Python的思维方式,还是我应该尽量简洁一些? 而且,如果我有点过于详尽,我应该改用类似的东西(大多数文档都无法通过该方法打印)吗? 问题答案: 看一下reStructuredT

  • 我已经用iText创建了一个文档,我想把这个文档(保存为PDF文件)转换成一个图像。为此,我使用PDFBox,它需要一个PDDocument作为输入。我使用以下代码: 此时,我从已保存的文件中加载文档。但我希望在Java内部执行此操作。 所以我的问题是:如何将文档转换为PDDocument? 非常感谢任何帮助!

  • Elasticsearch 提供实时获取文档的方法。这意味着只要文档被索引且客户端收到消息确认后,你就可以立即在任何的分片中检索文档。Get 操作通过 index/type/id 方式请求一个文档信息: $params = [ 'index' => 'my_index', 'type' => 'my_type', 'id' => 'my_id' ]; // Get doc

  • 我的firestore数据库中有两个集合,第一个是所有文档的列表(区块列表),第二个是用户的集合。当用户在应用程序上为帖子添加书签时,只将此帖子的id发送到子收藏(收藏夹)。 那么,如何根据第一个集合的ID显示该子集合的文档呢。 我使用此代码访问子集合ID列表,但我想知道如何使用它从主集合(区块列表)中获取适合此ID的文档。

  • 我正在尝试从检索或实例,而不将保存到文件系统。 中是否有任何方法从现有的返回或?