2012-10-03 8 views
8

Utilizzo l'API POI di apache per scrivere file XLSX. Poiché ho bisogno di scrivere file di grandi dimensioni, sto utilizzando l'API Streaming (SXSSF). Per fare ciò, sto seguendo la guida this. Si noti che alla fine dell'esempio c'è una chiamata aPOI Apache: SXSSFWorkbook.dispose() inesistente

wb.dispose 

Questo esempio wb riferisce a un'istanza SXSSFWorkbook. Sto usando lo stesso nel mio codice ma si lamenta del metodo di smaltimento non esistente. Ho scaricato il codice sorgente e il metodo non è presente. Tuttavia, andando al loro SVN e controllando che il codice di classe siamo in grado di vedere il metodo c'è:

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

Ho già provato a ricompilare il proprio codice, ma ho un sacco di errori ...

+0

Perché non checkout l'intera base di codice da SVN e costruire che con la formica? O prendi una build notturna di recente? – Gagravarr

+0

@Gagravarr La versione corrente è 3.9-beta1 e volevo davvero evitare di utilizzare API beta per i clienti ... –

+0

Se si desidera utilizzare nuove funzionalità, è necessario utilizzare nuove versioni ... – Gagravarr

risposta

7

A partire dal 2012-12-03, POI 3.9 è disponibile come versione stabile. Il metodo dispose() è disponibile in SXSSFWorkbook in questa versione.

(Naturalmente, questo non era il caso in cui la questione è stato chiesto.)

12

Il Apache POI 3.8 (ultima versione stabile al momento) crea un file XML temporaneo per ogni foglio (quando si utilizza SXSSF) ma non offre la possibilità di eliminare questi file. Questo fatto rende questa API non utilizzabile perché se esporto 600 MB di dati, avrò 2 file con 600 MB e uno di essi sarà nella cartella temporanea finché non verrà eliminato.

Scavando nel codice, vediamo che la classe SXSSFSheet ha un'istanza di SheetDataWriter. Quest'ultima classe è responsabile della scrittura e della gestione del file temporaneo rappresentato dall'istanza File. L'accesso a questo oggetto consentirebbe di eliminare il file. Tutte queste istanze sono private quindi, in teoria, non è possibile accedervi. Tuttavia, attraverso la riflessione, possiamo accedere all'istanza File per eliminare questi file utili ma noiosi!

Quanto segue ai metodi consentono di fare ciò. Chiamando lo deleteSXSSFTempFiles, tutti i file temporanei di quella cartella di lavoro vengono eliminati.

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