9

我正在使用 apache 的 POI API 来编写 XLSX 文件。由于我需要编写大文件,因此我使用了 Streaming API (SXSSF)。为此,我正在遵循指南。请注意,在示例结束时,会调用

wb.dispose

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

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

我已经尝试重新编译他们的代码,但我得到了很多错误......

4

2 回答 2

13

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

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

以下 to 方法允许执行此操作。通过调用deleteSXSSFTempFiles,该工作簿的所有临时文件都将被删除。

/**
 * 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-10-04T10:05:32.367 回答
7

自 2012-12-03 起,POI 3.9 可作为稳定版本使用。该dispose()方法SXSSFWorkbook在此版本中可用。

当然,提问的时候不是这样的。

于 2013-05-08T07:44:28.820 回答