POI Apache: SXSSFWorkbook.dispose() не существует

Я использую API-интерфейс Apache POI для записи файлов 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

Я уже пытался перекомпилировать их код, но получаю много ошибок...


person Miguel Ribeiro    schedule 03.10.2012    source источник
comment
Почему бы не взять всю кодовую базу из SVN и не построить ее с помощью ant? Или взять недавнюю ночную сборку?   -  person Gagravarr    schedule 03.10.2012
comment
@Gagravarr Текущая версия 3.9-beta1, и я действительно очень хотел избежать использования бета-API для клиентов ...   -  person Miguel Ribeiro    schedule 03.10.2012
comment
Если вы хотите использовать новые функции, вам нужно использовать новые версии...   -  person Gagravarr    schedule 04.10.2012


Ответы (2)


По состоянию на 03 декабря 2012 г. POI 3.9 доступен в виде стабильной версии. Метод dispose() доступен в SXSSFWorkbook в этом выпуске.

(Конечно, когда задавался вопрос, это было не так.)

person MaxH    schedule 08.05.2013

Apache POI 3.8 (последняя стабильная версия на тот момент) создает временный XML-файл для каждого листа (при использовании SXSSF), но не дает возможности удалить эти файлы. Этот факт делает этот API неудобным для использования, потому что, если я экспортирую 600 МБ данных, у меня будет 2 файла по 600 МБ, и один из них будет находиться во временной папке, пока не будет удален.

Копаясь в коде, мы видим, что класс 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
            }
        }
    }
}
person Miguel Ribeiro    schedule 04.10.2012