【问题标题】:PDFBox IO Exception: COSStream has been closed and cannot be readPDFBox IO 异常:COSStream 已关闭,无法读取
【发布时间】:2016-11-21 06:45:08
【问题描述】:

我在使用 PDFBox 用 Ja​​va 编写的一些代码时遇到问题。我正在尝试根据从 Excel 电子表格中读取的值使用特定表单填充 PDF。下面是我的类文件。

import java.io.FileInputStream;
import java.io.File;
import java.io.IOException;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;

import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.hssf.usermodel.*;

/**
 * This is a test file for reading and populating a PDF with specific forms
 */
public class JU_TestFile {

    PDPage Stick_Form;
    PDPage IKE_Form;
    PDPage BO_Form;

    /**
     * Constructor.
     */
    public JU_TestFile() throws IOException
    {
        this.BO_Form = (PDPage) PDDocument.load(new File("C:\\Users\\saf\\Desktop\\JavaTest\\BO Pole Form.pdf")).getPage(0);
        this.IKE_Form = (PDPage) PDDocument.load(new File("C:\\Users\\saf\\Desktop\\JavaTest\\IKE Form.pdf")).getPage(0);
        this.Stick_Form = (PDPage) PDDocument.load(new File("C:\\Users\\saf\\Desktop\\JavaTest\\Sticking Form.pdf")).getPage(0);
    }

    public void buildFile(String fileName, String excelSheet) throws IOException {
        // Create a Blank PDF Document and load in JU Excel Spreadsheet
        PDDocument workingDocument = new PDDocument();
        FileInputStream fis = new FileInputStream(new File(excelSheet));

        // Load in the workbook
        HSSFWorkbook JU_XML = new HSSFWorkbook(fis);

        int sheetNumber = 0;
        int rowNumber = 0;
        String cellValue = "Starting Value";

        HSSFSheet currentSheet = JU_XML.getSheetAt(sheetNumber);

        // While we have not reached the 25th row in our current sheet
        while (rowNumber <= 24) {
            // Get the value in the current row, on the 8th column in the xls file
            cellValue = currentSheet.getRow(rowNumber + 6).getCell(7).getStringCellValue();

            // If it has stuff in it, 
            if (cellValue != "") {
                // Check if it has the letters "IKE" and append the IKE form to our PDF
                if (cellValue != "IKE") {
                    workingDocument.importPage(IKE_Form);
                // If it is anything else (other than empty), append the Stick Form to our PDF  
                } else {
                    workingDocument.importPage(Stick_Form);

                }
                // Let's move on to the next row
                rowNumber++;

                // If the next row number is the "26th" row, we know we need to move on to the
                // next sheet, and also reset the rows to the first row of that next sheet
                if (rowNumber == 25) {
                    rowNumber = 0;
                    currentSheet = JU_XML.getSheetAt(++sheetNumber);
                }
            // if the 9th row is empty, we should break out of the loop and save/close our PDF, we are done
            } else {
                break;
            }
        }

        workingDocument.save(fileName);
        workingDocument.close();
    }
}

我收到以下错误: 线程“main”java.io.IOException 中的异常:COSStream 已关闭且无法读取。也许其封闭的 PDDocument 已关闭?

我已经完成了研究,在我运行 workingDocument.save(fileName) 命令之前,PDDocument 似乎正在关闭。我不太确定如何解决这个问题,而且我也有点迷失如何找到解决方法。我对我的编程有点生疏,所以任何帮助都会非常感激!此外,任何有关如何使未来的帖子内容更丰富的反馈都会很棒。

提前致谢

【问题讨论】:

  • 在您的构造函数中加载三个文档,但不将它们分配给任何变量。因此,垃圾收集将找到并关闭它们,在您的情况下,在 workingDocument.save 之前。只需将这些文档分配给成员变量并在不再需要它们时关闭它们,例如在终结器中。

标签: java apache pdfbox


【解决方案1】:

请尝试一下

PDFMergerUtility merger = new PDFMergerUtility();
PDDocument combine = PDDocument.load(file);
merger.appendDocument(getDocument(), combine);
merger.mergeDocuments();
combine.close();

更新: 由于merger.mergeDocuments(); 在最近的 API 中已被弃用,因此请尝试使用以下重载方法来使用相同的方法...

merger.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly());

merger.mergeDocuments(MemoryUsageSetting.setupTempFileOnly());

根据您的内存使用情况,您可以通过传递 MemoryUsageSetting 对象进一步微调此方法。

【讨论】:

  • 您的答案对我的问题很有效,我更新了答案以支持新版本的 Apache PDFBox。谢谢!
猜你喜欢
  • 1970-01-01
  • 2020-05-19
  • 2019-04-16
  • 2014-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-10
  • 2013-08-17
相关资源
最近更新 更多