9

Apache の POI API を使用して XLSX ファイルを作成しています。大きなファイルを書き込む必要があるため、ストリーミング 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 を使用する場合) が、これらのファイルを削除するオプションはありません。600MB のデータをエクスポートする場合、600MB のファイルが 2 つあり、そのうちの 1 つが削除されるまで一時フォルダーに置かれるため、この事実により、この API の使用は適切ではありません。

コードを掘り下げると、クラスSXSSFSheetに のインスタンスがあることがわかりますSheetDataWriter。この最後のクラスは、インスタンスによって表される一時ファイルの書き込みと維持を担当しFileます。このオブジェクトにアクセスすると、ファイルを削除できます。これらのインスタンスはすべてプライベートであるため、理論的にはアクセスできません。ただし、リフレクションを介して、インスタンスにアクセスして、Fileこの便利ではあるが迷惑なファイルを削除できます!

以下のメソッドでこれを行うことができます。を呼び出すと、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 月 3 日現在、POI 3.9 は安定版リリースとして利用できます。dispose()メソッドは、このリリースで使用できますSXSSFWorkbook

もちろん、質問されたときはそうではありませんでした。

于 2013-05-08T07:44:28.820 に答える