File io 关闭工作簿的文件句柄(apache poi)

File io 关闭工作簿的文件句柄(apache poi),file-io,apache-poi,File Io,Apache Poi,我使用WorkbookFactory.create(新文件(“path/to/xlsx”))构建了一个新工作簿。但是,当我在启动应用程序后尝试在Excel中编辑该文件时,会收到一条错误消息,表明该文件正在使用中。我必须释放文件吗?如果是,如何释放?(我在api文档中找不到类似于Workbook.close()的内容)或者我必须在其他地方查找吗 我不知道还有什么地方可以看;应用程序不会导致csv出现这些问题,对于excel文件,我只需调用转换器(xls=>csv),这是唯一的区别 (我使用的是PO

我使用
WorkbookFactory.create(新文件(“path/to/xlsx”))
构建了一个新工作簿。但是,当我在启动应用程序后尝试在Excel中编辑该文件时,会收到一条错误消息,表明该文件正在使用中。我必须释放文件吗?如果是,如何释放?(我在api文档中找不到类似于
Workbook.close()
的内容)或者我必须在其他地方查找吗

我不知道还有什么地方可以看;应用程序不会导致csv出现这些问题,对于excel文件,我只需调用转换器(xls=>csv),这是唯一的区别


(我使用的是POI 3.8)

如果您需要完全控制资源何时关闭,您应该自己提前创建OPC包,并将其传递到WorkbookFactory。OPCPackage提供了您所追求的close方法。工作簿将保持打开状态,直到垃圾回收

您的代码看起来像:

     File f = new File("/path/to/excel/file");
     Workbook wb = null;

     NPOIFSFileSystem npoifs = null;
     OPCPackage pkg = null;
     try {
       npoifs = new NPOIFSFileSystem(f);
       wb = WorkbookFactory.create(npoifs);
     } catch(OfficeXmlFileException ofe) {
       pkg = OPCPackage.open(f);
       wb = WorkbookFactory.create(pkg);
     }

     // Use it

     if (npoifs != null) { npoifs.close(); }
     if (pkg != null) { pkg.close(); }

在传递给
WorkbookFactory.create()
的InputStream上维护一个句柄,并在处理完工作簿后简单地关闭InputStream,这样看起来效果不错。例如:

    InputStream is = // initialize
    try {
        Workbook wb = WorkbookFactory.create(is);
        // use the workbook
    } finally {
        if (is != null) is.close()
    }
如何关闭Java中POI工作簿的实例:
首先,您需要关闭写入工作簿的流:

workBook.write(outputStream);

outputStream.close();
之后,您应关闭工作簿(无需进一步操作)并处理临时文件:

//Close the workBook
workBook.close();

//deleting the temporary files
workBook.dispose();

从2021年开始,我们就面临着同样的问题(,当使用poi版本3.9时

我只是发现,如果我们将poi版本升级到3.17(如果您仍然使用Java 7,那么哪种poi版本4或更高版本只支持Java 8或更高版本)

然后工作簿将实现
自动关闭

因此,可以使用
Try With Resources
块自动关闭文件

这是演示代码

try(工作簿=WorkbookFactory.create(新文件(文件位置))){
//在这里操作工作簿。。。
}
我认为上面的代码比@Gagravarr解决方案要好,因为它复制了create方法在外部所做的工作,不熟悉poi库的开发人员不知道它是什么


附言。
事实上,这个问题在bugzilla中是作为一个bug存在的,请参阅,并且已解决,代码已合并到poi 3.11或更高版本中。因此,任何与我们有相同问题的人都可以查看它,并在使用完它后关闭资源。

谢谢,我将试一试。为什么工作簿.create不释放文件指针?我的浅薄理解ding认为文件对象不是文件指针,因为你不能对它们执行IO。因此我假设
Workbook.create
确实为IO打开了文件,如果它打开了,为什么不能也关闭它?(我认为你对这个主题有见解,只是一个粗略的猜测,但你在POI上工作?)我对它进行了测试,效果很好。非常感谢。我自由地编辑了你的awnser。你有什么理由在处理工作簿时保持文件打开吗?文件保持打开状态,这样当你写下对新流的更改时,文件的其他部分(如嵌入资源)就会被删除可以流式输出到OK,那么利用
工作簿的功能有什么问题。创建
来区分xls/xlsx?为什么还要删除该部分?(如果没有问题,我可能会将其作为单独的awnser重新发布,不用担心您的awnser会被接受)如果您想完全控制资源的关闭,则需要控制将文件包装到打开的对象中。如果您不介意自动关闭或切换到unix系统,则
Workbook.create(file)
应该很好!很好。如果你知道你将执行只读操作,你也可以在创建工作簿后立即关闭InputStream,因为它会存储在内存中。我个人觉得它更明确。关闭wb怎么样?@ArnaudP你确定吗?我试过了,得到了一个有缺陷的文件。这与Ga相矛盾gravarr对他的回答的评论。@JosefScript这是很久以前的事了,我添加这条评论是因为它在我的案例中有效,但我肯定不是这方面的专家。为了安全起见,我很想删除它,但它有4票,所以我不知道。这似乎并没有关闭工作簿,只是关闭底层流。而且,它的内存比使用Fil更高对象,请参见仅供参考的SXSSF实现has dispose()方法
//Close the workBook
workBook.close();

//deleting the temporary files
workBook.dispose();