Apache POI 3.8 (najnowsza stabilna w tym czasie) tworzy tymczasowy plik XML dla każdego arkusza (przy użyciu SXSSF), ale nie daje możliwości usunięcia tych plików. Fakt ten sprawia, że ten interfejs API nie jest dobry w użyciu, ponieważ jeśli wyeksportuję 600 MB danych, będę miał 2 pliki z 600 MB i jedno z nich będzie w folderze tymczasowym, dopóki nie zostanie usunięte.
Pogrzebanie kodu, widzimy, że klasa SXSSFSheet
ma instancję SheetDataWriter
. Ta ostatnia klasa jest odpowiedzialna za zapisanie i zachowanie pliku tymczasowego reprezentowanego przez instancję File
. Uzyskanie dostępu do tego obiektu pozwoliłoby na usunięcie pliku. Wszystkie te wystąpienia są prywatne, więc teoretycznie nie można uzyskać do nich dostępu. Jednak dzięki refleksji możemy uzyskać dostęp do instancji File
, aby usunąć te przydatne, ale denerwujące pliki!
Następujące metody pozwalają to zrobić. Po wywołaniu deleteSXSSFTempFiles
wszystkie tymczasowe pliki tego skoroszytu zostaną usunięte.
/**
* 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
}
}
}
}
Dlaczego nie kasa cały codebase z SVN i zbudować że z mrówki? Lub pobrać ostatnią nocną kompilację? – Gagravarr
@Gagravarr Obecna wersja to 3.9-beta1 i naprawdę chciałem uniknąć używania API beta dla klientów ... –
Jeśli chcesz korzystać z nowych funkcji, musisz użyć nowych wydań ... – Gagravarr