PDFBox:拆分 PDF 并添加书签 IOException
PDFBox: Split PDF and add bookmarks IOException
在我的项目中,我通过书签拆分了一个 pdf 文件。应创建一个新的 pdf 文件,其中包含拆分的页面和一些新书签。
这会导致以下异常:
线程异常"main" java.io.IOException: COSStream 已关闭,无法读取。也许其封闭的 PDDocument 已被关闭?
如果我删除 outline.addLast(pagesOutline);
行,新的 pdf 包含拆分的页面(无一例外)但显然不是书签。我认为我尝试添加书签的方式有问题。
我的代码:
private void tryCreatePDF(List<String> listOfBookmarks) throws IOException
{
document = PDDocument.load(new File("C:/Users/me/Desktop/existingpdf.pdf"));
PDDocumentCatalog catalog = document.getDocumentCatalog();
PDDocumentOutline bookmarksInExistingFile = catalog.getDocumentOutline();
destinationPDF = new PDDocument();
outline = new PDDocumentOutline();
destinationPDF.getDocumentCatalog().setDocumentOutline(outline);
pagesOutline = new PDOutlineItem();
pagesOutline.setTitle("First Bookmark");
outline.addLast(pagesOutline);
for(String bookmarkToSplit : listOfBookmarks)
{
addPagesFromExistingFileToNewPDF(bookmarksInExistingFile, bookmarkToSplit);
}
createNewPDF();
}
private void addPagesFromExistingFileToNewPDF(PDOutlineNode outlineNodeFromExistingPDF, String bookmarkToSplit) throws IOException
{
PDOutlineItem current = outlineNodeFromExistingPDF.getFirstChild();
while(current != null)
{
PDPage currentPage = current.findDestinationPage(document);
Integer pageNumber = document.getDocumentCatalog().getPages().indexOf(currentPage) + 1;
addPagesFromExistingFileToNewPDF(current, bookmarkToSplit);
String bookmark = current.getTitle().trim();
if(bookmark.matches(bookmarkToSplit + "\s.+"))
{
Splitter splitter = new Splitter();
splitter.setStartPage(pageNumber);
splitter.setEndPage(pageNumber);
List<PDDocument> pages = splitter.split(document);
addPagesToNewDocument(pages);
}
current = current.getNextSibling();
}
}
private void addPagesToNewDocument(List<PDDocument> pages) throws IOException
{
PDFMergerUtility pdfMergerUtility = new PDFMergerUtility();
for(int index = 0; index < pages.size(); index++)
{
PDDocument doc = pages.get(index);
pdfMergerUtility.appendDocument(destinationPDF, doc);
if(index == 0)
{
addNewBookmarkToNewPDF(doc);
}
doc.close();
}
}
private void addNewBookmarkToNewPDF(PDDocument doc)
{
PDPageFitWidthDestination dest = new PDPageFitWidthDestination();
dest.setPage(doc.getPage(0));
PDOutlineItem bookmark = new PDOutlineItem();
bookmark.setDestination(dest);
bookmark.setTitle("Child Bookmark");
pagesOutline.addLast(bookmark);
}
private void createNewPDF() throws IOException
{
File targetFile = new File("C:/Users/me/Desktop/newpdf.pdf");
pagesOutline.openNode();
outline.openNode();
destinationPDF.save(targetFile);
destinationPDF.close();
document.close();
}
堆栈跟踪:
Exception in thread "main" java.io.IOException: COSStream has been closed and cannot be read. Perhaps its enclosing PDDocument has been closed?
at org.apache.pdfbox.cos.COSStream.checkClosed(COSStream.java:77)
at org.apache.pdfbox.cos.COSStream.createRawInputStream(COSStream.java:125)
at org.apache.pdfbox.pdfwriter.COSWriter.visitFromStream(COSWriter.java:1203)
at org.apache.pdfbox.cos.COSStream.accept(COSStream.java:383)
at org.apache.pdfbox.pdfwriter.COSWriter.doWriteObject(COSWriter.java:522)
at org.apache.pdfbox.pdfwriter.COSWriter.doWriteObjects(COSWriter.java:460)
at org.apache.pdfbox.pdfwriter.COSWriter.doWriteBody(COSWriter.java:444)
at org.apache.pdfbox.pdfwriter.COSWriter.visitFromDocument(COSWriter.java:1099)
at org.apache.pdfbox.cos.COSDocument.accept(COSDocument.java:419)
at org.apache.pdfbox.pdfwriter.COSWriter.write(COSWriter.java:1370)
at org.apache.pdfbox.pdfwriter.COSWriter.write(COSWriter.java:1257)
at org.apache.pdfbox.pdmodel.PDDocument.save(PDDocument.java:1267)
at org.apache.pdfbox.pdmodel.PDDocument.save(PDDocument.java:1238)
at askWhosebug.SplitPDFByBookmarks.createNewPDF(SplitPDFByBookmarks.java:126)
at askWhosebug.SplitPDFByBookmarks.tryCreatePDF(SplitPDFByBookmarks.java:55)
at askWhosebug.SplitPDFByBookmarks.<init>(SplitPDFByBookmarks.java:33)
at askWhosebug.Main.main(Main.java:9)
编辑:
@本题的以下所有读者:
解决问题后,我的程序没有按预期运行。 (每个书签都指向第一页。)但是这个问题不是这个问题的一部分。
addPagesToNewDocument()
结束还为时过早。这也会关闭源文档中的资源,因为这些资源被两者使用。最好在所有文档都保存后才开始关闭。
在我的项目中,我通过书签拆分了一个 pdf 文件。应创建一个新的 pdf 文件,其中包含拆分的页面和一些新书签。
这会导致以下异常:
线程异常"main" java.io.IOException: COSStream 已关闭,无法读取。也许其封闭的 PDDocument 已被关闭?
如果我删除 outline.addLast(pagesOutline);
行,新的 pdf 包含拆分的页面(无一例外)但显然不是书签。我认为我尝试添加书签的方式有问题。
我的代码:
private void tryCreatePDF(List<String> listOfBookmarks) throws IOException
{
document = PDDocument.load(new File("C:/Users/me/Desktop/existingpdf.pdf"));
PDDocumentCatalog catalog = document.getDocumentCatalog();
PDDocumentOutline bookmarksInExistingFile = catalog.getDocumentOutline();
destinationPDF = new PDDocument();
outline = new PDDocumentOutline();
destinationPDF.getDocumentCatalog().setDocumentOutline(outline);
pagesOutline = new PDOutlineItem();
pagesOutline.setTitle("First Bookmark");
outline.addLast(pagesOutline);
for(String bookmarkToSplit : listOfBookmarks)
{
addPagesFromExistingFileToNewPDF(bookmarksInExistingFile, bookmarkToSplit);
}
createNewPDF();
}
private void addPagesFromExistingFileToNewPDF(PDOutlineNode outlineNodeFromExistingPDF, String bookmarkToSplit) throws IOException
{
PDOutlineItem current = outlineNodeFromExistingPDF.getFirstChild();
while(current != null)
{
PDPage currentPage = current.findDestinationPage(document);
Integer pageNumber = document.getDocumentCatalog().getPages().indexOf(currentPage) + 1;
addPagesFromExistingFileToNewPDF(current, bookmarkToSplit);
String bookmark = current.getTitle().trim();
if(bookmark.matches(bookmarkToSplit + "\s.+"))
{
Splitter splitter = new Splitter();
splitter.setStartPage(pageNumber);
splitter.setEndPage(pageNumber);
List<PDDocument> pages = splitter.split(document);
addPagesToNewDocument(pages);
}
current = current.getNextSibling();
}
}
private void addPagesToNewDocument(List<PDDocument> pages) throws IOException
{
PDFMergerUtility pdfMergerUtility = new PDFMergerUtility();
for(int index = 0; index < pages.size(); index++)
{
PDDocument doc = pages.get(index);
pdfMergerUtility.appendDocument(destinationPDF, doc);
if(index == 0)
{
addNewBookmarkToNewPDF(doc);
}
doc.close();
}
}
private void addNewBookmarkToNewPDF(PDDocument doc)
{
PDPageFitWidthDestination dest = new PDPageFitWidthDestination();
dest.setPage(doc.getPage(0));
PDOutlineItem bookmark = new PDOutlineItem();
bookmark.setDestination(dest);
bookmark.setTitle("Child Bookmark");
pagesOutline.addLast(bookmark);
}
private void createNewPDF() throws IOException
{
File targetFile = new File("C:/Users/me/Desktop/newpdf.pdf");
pagesOutline.openNode();
outline.openNode();
destinationPDF.save(targetFile);
destinationPDF.close();
document.close();
}
堆栈跟踪:
Exception in thread "main" java.io.IOException: COSStream has been closed and cannot be read. Perhaps its enclosing PDDocument has been closed?
at org.apache.pdfbox.cos.COSStream.checkClosed(COSStream.java:77)
at org.apache.pdfbox.cos.COSStream.createRawInputStream(COSStream.java:125)
at org.apache.pdfbox.pdfwriter.COSWriter.visitFromStream(COSWriter.java:1203)
at org.apache.pdfbox.cos.COSStream.accept(COSStream.java:383)
at org.apache.pdfbox.pdfwriter.COSWriter.doWriteObject(COSWriter.java:522)
at org.apache.pdfbox.pdfwriter.COSWriter.doWriteObjects(COSWriter.java:460)
at org.apache.pdfbox.pdfwriter.COSWriter.doWriteBody(COSWriter.java:444)
at org.apache.pdfbox.pdfwriter.COSWriter.visitFromDocument(COSWriter.java:1099)
at org.apache.pdfbox.cos.COSDocument.accept(COSDocument.java:419)
at org.apache.pdfbox.pdfwriter.COSWriter.write(COSWriter.java:1370)
at org.apache.pdfbox.pdfwriter.COSWriter.write(COSWriter.java:1257)
at org.apache.pdfbox.pdmodel.PDDocument.save(PDDocument.java:1267)
at org.apache.pdfbox.pdmodel.PDDocument.save(PDDocument.java:1238)
at askWhosebug.SplitPDFByBookmarks.createNewPDF(SplitPDFByBookmarks.java:126)
at askWhosebug.SplitPDFByBookmarks.tryCreatePDF(SplitPDFByBookmarks.java:55)
at askWhosebug.SplitPDFByBookmarks.<init>(SplitPDFByBookmarks.java:33)
at askWhosebug.Main.main(Main.java:9)
编辑:
@本题的以下所有读者:
解决问题后,我的程序没有按预期运行。 (每个书签都指向第一页。)但是这个问题不是这个问题的一部分。
addPagesToNewDocument()
结束还为时过早。这也会关闭源文档中的资源,因为这些资源被两者使用。最好在所有文档都保存后才开始关闭。