Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java PDFBox将锁定JPEG输入文件,直到应用程序退出_Java_Pdf_Pdfbox_Filelock - Fatal编程技术网

Java PDFBox将锁定JPEG输入文件,直到应用程序退出

Java PDFBox将锁定JPEG输入文件,直到应用程序退出,java,pdf,pdfbox,filelock,Java,Pdf,Pdfbox,Filelock,我在Windows7环境中使用PDFBox RC2,Java 1.8_66。我用它从一组200dpi的页面大小的图像文件(包括JPEG和PNG)中创建了一个PDF 事实证明,将JPEG文件添加到PDF时,PDImageXObject.createFromFile()例程无法关闭内部文件句柄,从而在应用程序的生命周期内锁定图像文件。将PNG文件添加到PDF时,没有问题 下面是一些重现该问题的示例代码。使用process explorer(从sysinternals),查看java.exe进程的打开

我在Windows7环境中使用PDFBox RC2,Java 1.8_66。我用它从一组200dpi的页面大小的图像文件(包括JPEG和PNG)中创建了一个PDF

事实证明,将JPEG文件添加到PDF时,PDImageXObject.createFromFile()例程无法关闭内部文件句柄,从而在应用程序的生命周期内锁定图像文件。将PNG文件添加到PDF时,没有问题

下面是一些重现该问题的示例代码。使用process explorer(从sysinternals),查看java.exe进程的打开文件句柄并运行此代码。我的测试使用了大约20个完整大小的JPEG文件。请注意,在方法退出后,仍有几个锁定的文件保留在后面

public Boolean CreateFromImages_Broken(String pdfFilename, String[] imageFilenames) {

    PDDocument doc = new PDDocument();        
    for (String imageFilename : imageFilenames) {

        try {
            PDPage page = new PDPage();
            doc.addPage(page);

            PDImageXObject pdImage = PDImageXObject.createFromFile(imageFilename, doc);

            // at this point, if the imageFilename is a jpeg, pdImage holds onto a handle for 
            // the given imageFilename and that file remains locked until the application is closed

            try (PDPageContentStream contentStream = new PDPageContentStream(doc, page)) {
                float scale = (float)72.0 / 200;
                page.setMediaBox(new PDRectangle((int)(pdImage.getWidth() * scale), (int)(pdImage.getHeight() * scale)));
                contentStream.drawImage(pdImage, 0, 0, pdImage.getWidth()*scale, pdImage.getHeight()*scale);
            }
        } catch (IOException ioe) {
            return false;
        }                          
    }

    try {
        doc.save(pdfFilename);
        doc.close();                  
    } catch (IOException ex) {
        return false;
    }

    return true;
} 

作为一种解决方法,我回顾了PNG和JPEG处理的源代码,并成功地实现了这一点,它似乎适用于两种文件类型:

public Boolean CreateFromImages_FIXED(String pdfFilename, String[] imageFilenames) {

    PDDocument doc = new PDDocument();        
    for (String imageFilename : imageFilenames) {

        FileInputStream fis = null;

        try {
            PDPage page = new PDPage();
            doc.addPage(page);

            PDImageXObject pdImage = null;

            // work around JPEG issue by opening up our own stream, with which
            // we can close ourselves instead of PDFBOX leaking it. For PNG
            // images, the createFromFile seems to be OK
            if (imageFilename.toLowerCase().endsWith(".jpg")) {
                fis = new FileInputStream(new File(imageFilename));
                pdImage = JPEGFactory.createFromStream(doc, fis);
            } else {
                pdImage = PDImageXObject.createFromFile(imageFilename, doc);
            }

            try (PDPageContentStream contentStream = new PDPageContentStream(doc, page)) {
                float scale = (float)72.0 / 200;
                page.setMediaBox(new PDRectangle((int)(pdImage.getWidth() * scale), (int)(pdImage.getHeight() * scale)));
                contentStream.drawImage(pdImage, 0, 0, pdImage.getWidth()*scale, pdImage.getHeight()*scale);                    

                if (fis != null) {
                    fis.close();
                    fis = null;
                }                    
            }

        } catch (IOException ioe) {
            return false;
        }                          
    }

    try {
        doc.save(pdfFilename);
        doc.close();                  
    } catch (IOException ex) {
        return false;
    }

    return true;        
}

实际上,关闭
fis
不需要等待太长时间,因为
JPEGFactory.createFromStream(doc,fis)
已经将整个流读取到
字节[]
。在PDFBOX-3199中修复。谢谢你找到这个bug。顺便说一句,目前的版本是RC3。(它也有这个bug)。谢谢@TilmanHausherr!期待修复!它是固定的。您可以通过使用快照来使用修复,请参阅