2012-10-03 18 views
8

Ich benutze Apaches POI API, um XLSX-Dateien zu schreiben. Da ich große Dateien schreiben muss, verwende ich die Streaming API (SXSSF). Dazu folge ich this Guide. Beachten Sie, dass Apache POI: SXSSFWorkbook.dispose() existiert nicht

wb.dispose 

zu einer SXSSFWorkbook Instanz Dieses wb Beispiel bezieht sich auf

bis Ende des Beispiels einen Anruf gibt. Ich benutze das gleiche in meinem Code, aber es beschwert sich über die dispose-Methode nicht vorhanden. Ich habe den Quellcode heruntergeladen und die Methode ist nicht da. Allerdings gehen ihre SVN und Überprüfung dieser Klasse Code wir die Methode dort sehen können:

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

ich bereits versucht, ihren Code neu kompilieren, aber ich habe eine Menge Fehler bekommen ...

+0

Warum nicht die ganze Code-Basis von SVN Kasse und das mit Ameise bauen? Oder eine aktuelle Nightly Build greifen? – Gagravarr

+0

@Gagravarr Die aktuelle Version 3.9-beta 1 ist, und ich wollte wirklich, wirklich mit Beta-APIs für die Kunden vermeiden ... –

+0

Wenn Sie neue Funktionen nutzen möchten, dann müssen Sie neue Versionen verwenden ... – Gagravarr

Antwort

7

Seit 2012-12-03 ist POI 3.9 als stabile Version verfügbar. Die dispose() Methode ist in SXSSFWorkbook in dieser Version verfügbar.

(Natürlich war dies nicht der Fall, wenn die Frage gestellt wurde.)

12

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 
      } 
     } 
    } 
}