Die Apache POI 3.8 (zuletzt stabil zu der Zeit) erstellt eine temporäre XML-Datei für jedes Blatt (bei Verwendung von SXSSF), bietet jedoch keine Option zum Löschen dieser Dateien. Diese Tatsache macht diese API nicht gut zu verwenden, denn wenn ich 600MB Daten exportiere, dann habe ich 2 Dateien mit 600MB und einer davon wird im temporären Ordner sein, bis er gelöscht wird.
In den Code eintauchen, sehen wir, dass die Klasse SXSSFSheet
eine Instanz von SheetDataWriter
hat. Diese letzte Klasse ist verantwortlich für das Schreiben und Verwalten der temporären Datei, die durch die File
-Instanz dargestellt wird. Wenn Sie auf dieses Objekt zugreifen, können Sie die Datei löschen. Alle diese Instanzen sind privat, daher können Sie theoretisch nicht darauf zugreifen. Durch Reflektion können wir jedoch auf die File
Instanz zugreifen, um diese nützlichen aber lästigen Dateien zu löschen!
Die folgenden Methoden ermöglichen es, dies zu tun. Durch Aufruf der deleteSXSSFTempFiles
werden alle temporären Dateien dieser Arbeitsmappe gelöscht.
/**
* 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
}
}
}
}
Warum nicht die ganze Code-Basis von SVN Kasse und das mit Ameise bauen? Oder eine aktuelle Nightly Build greifen? – Gagravarr
@Gagravarr Die aktuelle Version 3.9-beta 1 ist, und ich wollte wirklich, wirklich mit Beta-APIs für die Kunden vermeiden ... –
Wenn Sie neue Funktionen nutzen möchten, dann müssen Sie neue Versionen verwenden ... – Gagravarr