关于excel:Apache POI:SXSSFWorkbook.dispose()不存在

Apache POI: SXSSFWorkbook.dispose() does not exist

我正在使用apache的POI API来编写XLSX文件。 由于我需要编写大文件,因此我在使用Streaming API(SXSSF)。
为此,我正在遵循本指南。 请注意,在示例末尾有一个调用

1
wb.dispose

此wb实例引用SXSSFWorkbook实例。 我在代码中使用了相同的内容,但它抱怨不存在dispose方法。 我下载了源代码,但该方法不存在。 但是,转到他们的SVN并检查该类的代码,我们可以在此处看到该方法:

https://svn.apache.org/repos/asf/poi/trunk/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java

我已经尝试过重新编译他们的代码,但是却遇到很多错误...


Apache POI 3.8(当时最新稳定)是为每个工作表创建一个临时XML文件(使用SXSSF时),但没有提供删除这些文件的选项。这个事实使该API不能很好地使用,因为如果我要导出600MB的数据,那么我将拥有2个600MB的文件,其中一个将位于临时文件夹中,直到被删除。

深入研究代码,我们看到类SXSSFSheet具有SheetDataWriter的实例。最后一个类负责编写和维护File实例表示的临时文件。访问该对象将允许删除文件。
所有这些实例都是私有的,因此,从理论上讲,您将无法访问它们。但是,通过反射,我们可以访问File实例以删除此有用但令人讨厌的文件!

下面的方法可以做到这一点。通过调用deleteSXSSFTempFiles,将删除该工作簿的所有临时文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/**
 * Returns a private attribute of a class
 * @param containingClass The class that contains the private attribute to retrieve
 * @param fieldToGet The name of the attribute to get
 * @return The private attribute
 * @throws NoSuchFieldException
 * @throws IllegalAccessException
 */
public static Object getPrivateAttribute(Object containingClass, String fieldToGet) throws NoSuchFieldException, IllegalAccessException {
    //get the field of the containingClass instance
    Field declaredField = containingClass.getClass().getDeclaredField(fieldToGet);
    //set it as accessible
    declaredField.setAccessible(true);
    //access it
    Object get = declaredField.get(containingClass);
    //return it!
    return get;
}

/**
 * Deletes all temporary files of the SXSSFWorkbook instance
 * @param workbook
 * @throws NoSuchFieldException
 * @throws IllegalAccessException
 */
public static void deleteSXSSFTempFiles(SXSSFWorkbook workbook) throws NoSuchFieldException, IllegalAccessException {

    int numberOfSheets = workbook.getNumberOfSheets();

    //iterate through all sheets (each sheet as a temp file)
    for (int i = 0; i < numberOfSheets; i++) {
        Sheet sheetAt = workbook.getSheetAt(i);

        //delete only if the sheet is written by stream
        if (sheetAt instanceof SXSSFSheet) {
            SheetDataWriter sdw = (SheetDataWriter) getPrivateAttribute(sheetAt,"_writer");
            File f = (File) getPrivateAttribute(sdw,"_fd");

            try {
                f.delete();
            } catch (Exception ex) {
                //could not delete the file
            }
        }
    }
}

从2012年12月3日起,POI 3.9可以作为稳定版本发布。在本发行版的SXSSFWorkbook中提供了dispose()方法。

(当然,在询问问题时情况并非如此。)