Java 使用PDFBox复制pdf是否可以像使用iText一样小?

Java 使用PDFBox复制pdf是否可以像使用iText一样小?,java,itext,pdfbox,Java,Itext,Pdfbox,我正在阅读一份PDF文件,并输出一份包含多份原始PDF副本的PDF文件。我通过对和做同样的事情来进行测试。如果我单独复制每个页面,iText将创建更小的输出 问题是:在PDFBox中是否有其他方法可以实现这一点,从而产生更小的输出PDF 对于一个示例输入文件,使用两种工具生成两个输出副本: 原始PDF大小:30K PDFBox v 1.7.1生成的PDF:84K iText v 5.3.4生成的PDF:35K PDFBox的Java代码很抱歉给您造成错误处理。注意它是如何反复读取输入并将其作为一

我正在阅读一份PDF文件,并输出一份包含多份原始PDF副本的PDF文件。我通过对和做同样的事情来进行测试。如果我单独复制每个页面,iText将创建更小的输出

问题是:在PDFBox中是否有其他方法可以实现这一点,从而产生更小的输出PDF

对于一个示例输入文件,使用两种工具生成两个输出副本:

原始PDF大小:30K PDFBox v 1.7.1生成的PDF:84K iText v 5.3.4生成的PDF:35K PDFBox的Java代码很抱歉给您造成错误处理。注意它是如何反复读取输入并将其作为一个整体复制的:

PDFMergerUtility merger = new PDFMergerUtility();
PDDocument workplace = null;
try {
    for (int cnt = 0; cnt < COPIES; ++cnt) {
        PDDocument document = null;
        InputStream stream = null;
        try {
            stream = new FileInputStream(new File(sourceFileName));
            document = PDDocument.load(stream);
            if (workplace == null) {
                workplace = document;
            } else {
                merger.appendDocument(workplace, document);
            }
        } finally {
            if (document != null && document != workplace) {
                document.close();
            }
            if (stream != null) {
                stream.close();
            }
        }
    }

    OutputStream out = null;
    try {
        out = new FileOutputStream(new File(destinationFileName));
        workplace.save(out);
    } finally {
        if (out != null) {
            out.close();
        }
    }
} catch (COSVisitorException e1) {
    e1.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (workplace != null) {
        try {
            workplace.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

使用以下解决方案,我能够创建一个包含许多重复页面的PDF文件,并且对存储的影响最小

PDDocument samplePdf = null;
try {
    samplePdf = PDDocument.load(PDF_PATH);
    PDPage page = (PDPage) samplePdf.getDocumentCatalog().getAllPages().get(0); 

    for(int i = 0; i < COPIES; i++) {
        samplePdf.importPage(page);
    }

    samplePdf.save(SAVE_PATH); //$NON-NLS-1$

} catch (IOException e) {
    e.printStackTrace();
} catch (COSVisitorException e) {
    e.printStackTrace();
}

在我的第一次尝试中,我使用了samplePdf.addPagepage,但它没有按预期工作。所以很明显,add和import函数之间存在差异。我必须检查源代码或文档以了解原因。无论如何,这将帮助您设计一个解决方案来满足您对PDFBox的需求。

使用以下解决方案,我能够创建一个包含许多重复页面的PDF文件,并且对存储的影响最小

PDDocument samplePdf = null;
try {
    samplePdf = PDDocument.load(PDF_PATH);
    PDPage page = (PDPage) samplePdf.getDocumentCatalog().getAllPages().get(0); 

    for(int i = 0; i < COPIES; i++) {
        samplePdf.importPage(page);
    }

    samplePdf.save(SAVE_PATH); //$NON-NLS-1$

} catch (IOException e) {
    e.printStackTrace();
} catch (COSVisitorException e) {
    e.printStackTrace();
}

在我的第一次尝试中,我使用了samplePdf.addPagepage,但它没有按预期工作。所以很明显,add和import函数之间存在差异。我必须检查源代码或文档以了解原因。无论如何,这将有助于你设计一个解决方案来满足你对PDFBox的需求。

IMHO这是一个关于经济学的问题,而不是一个纯粹的技术问题。您有一个使用iText的工作解决方案,但您希望使用PdfBox。这种选择是有代价的。我想你更喜欢PdfBox是因为ASL。然而,由于没有人为PdfBox付费,所以您不应该期望该库速度快、功能丰富、完整,。。。我在2009年将iText许可证从MPL/AGPL更改为AGPL,因为我需要开始创收以确保库的进一步开发。如果没有这笔收入,iText将慢慢消亡。@BrunoLowagie我理解你的意思,但由于我不是这两个图书馆的专家,我找到了一个可行的解决方案。也许还有另一种使用PDFBox的解决方案,可以创建更小的PDF文件。也许不是。也许iText在这方面更适合我的需要。我只是想从这两种工具的专家那里得到一些帮助。这就提出了一个问题,因为您是iText的专家,我是否有在iText中创建重复页面的最佳解决方案?PdfSmartCopy会在内存中保留某些对象的散列,例如早期版本的iText中的流和最新版本中的字体字典。每当重用对象时,我们都会添加对原始对象的引用,而不是像使用PdfCopy而不是PdfSmartCopy那样复制它。Acrobat甚至做得更好:Acrobat可以将同一字体的不同子集合并成一个更大的子集。我们还不支持这一点,因为它涉及重写整个内容流,而不是琐碎的内容+需要更多的CPU/内存。这与其说是一个纯粹的技术问题,不如说是一个经济学问题。您有一个使用iText的工作解决方案,但您希望使用PdfBox。这种选择是有代价的。我想你更喜欢PdfBox是因为ASL。然而,由于没有人为PdfBox付费,所以您不应该期望该库速度快、功能丰富、完整,。。。我在2009年将iText许可证从MPL/AGPL更改为AGPL,因为我需要开始创收以确保库的进一步开发。如果没有这笔收入,iText将慢慢消亡。@BrunoLowagie我理解你的意思,但由于我不是这两个图书馆的专家,我找到了一个可行的解决方案。也许还有另一种使用PDFBox的解决方案,可以创建更小的PDF文件。也许不是。也许iText在这方面更适合我的需要。我只是想从这两种工具的专家那里得到一些帮助。这就提出了一个问题,因为您是iText的专家,我是否有在iText中创建重复页面的最佳解决方案?PdfSmartCopy会在内存中保留某些对象的散列,例如早期版本的iText中的流和最新版本中的字体字典。每当重用对象时,我们都会添加对原始对象的引用,而不是像使用PdfCopy而不是PdfSmartCopy那样复制它。Acrobat甚至做得更好:Acrobat可以将同一字体的不同子集合并成一个更大的子集。我们还不支持,因为它涉及重写整个内容流,而不是琐碎的+需要更多的CPU/内存。您的方法生成的文件要小得多。例如,对于一个67K的原始1页文件,我运行您的代码,将副本设置为1,以获得一个78K的文件。使用我的方法,其中包含2的文件是133K。请注意,要复制具有多个页面的文档,很容易将.get0更改为该列表中所有页面的循环。我还
需要注意的是,在导入页面之前,克隆要添加的页面是最安全的。我遇到了一个麻烦。我从PDFMergeUtility.java获取了克隆代码。PDPage newPage=新PDPage COSDictionarycloner.cloneForNewDocument page.getCOSDictionary;这仍然节省了磁盘空间,可能会使用更多内存,但它避免了上面链接中详述的复杂问题。在解决PDFBOX-785后,下一个版本1.8.9应该会带来更小的文件,importPage中存在一个错误,即内容流没有被压缩。您的方法会生成更小的文件。例如,对于一个67K的原始1页文件,我运行您的代码,将副本设置为1,以获得一个78K的文件。使用我的方法,其中包含2的文件是133K。请注意,要复制具有多个页面的文档,很容易将.get0更改为该列表中所有页面的循环。我还需要注意,在导入之前克隆正在添加的页面是最安全的。我遇到了一个麻烦。我从PDFMergeUtility.java获取了克隆代码。PDPage newPage=新PDPage COSDictionarycloner.cloneForNewDocument page.getCOSDictionary;这仍然节省了磁盘空间,可能会使用更多内存,但它避免了上面链接中详述的复杂问题。解决PDFBOX-785后,下一个版本1.8.9应该会带来更小的文件,importPage中有一个错误,即内容流没有被压缩。
PDDocument samplePdf = null;
try {
    samplePdf = PDDocument.load(PDF_PATH);
    PDPage page = (PDPage) samplePdf.getDocumentCatalog().getAllPages().get(0); 

    for(int i = 0; i < COPIES; i++) {
        samplePdf.importPage(page);
    }

    samplePdf.save(SAVE_PATH); //$NON-NLS-1$

} catch (IOException e) {
    e.printStackTrace();
} catch (COSVisitorException e) {
    e.printStackTrace();
}