2012-10-03 31 views
8

Estoy usando la API POI de apache para escribir archivos XLSX. Como necesito escribir archivos grandes, estoy usando Streaming API (SXSSF). Para hacer esto, estoy siguiendo la guía this. Tenga en cuenta que para el final del ejemplo hay una llamada aApache POI: SXSSFWorkbook.dispose() no existe

wb.dispose 

Esta instancia wb se refiere a una instancia SXSSFWorkbook. Estoy usando lo mismo en mi código, pero se queja de que el método de eliminación no existe. Descargué el código fuente y el método no está allí. Sin embargo, ir a su SVN y la comprobación de que el código de clase podemos ver el método allí:

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

ya que trataron de volver a compilar el código pero consigo una gran cantidad de errores ...

+0

porqué no mire todo el código base de SVN y construir esa con la hormiga? ¿O tomar una construcción nocturna reciente? – Gagravarr

+0

@Gagravarr La versión actual es 3.9-beta1 y realmente quería evitar el uso de API beta para clientes ... –

+0

Si desea usar nuevas funciones, entonces necesita usar nuevas versiones ... – Gagravarr

Respuesta

7

A partir del 2012-12-03, POI 3.9 está disponible como una versión estable. El método dispose() está disponible en SXSSFWorkbook en esta versión.

(Por supuesto, esto no fue el caso cuando se hizo la pregunta.)

12

El Apache POI 3.8 (último estable en el momento) crea un archivo XML temporal para cada hoja (cuando se usa SXSSF) pero no da la opción de eliminar estos archivos. Este hecho hace que esta API no sea buena para usar porque si estoy exportando 600MB de datos, tendré 2 archivos con 600MB y uno de ellos estará en la carpeta temporal hasta que se elimine.

Introduciendo el código, vemos que la clase SXSSFSheet tiene una instancia de SheetDataWriter. Esta última clase es responsable de escribir y mantener el archivo temporal representado por la instancia File. El acceso a este objeto permitiría eliminar el archivo. Todas estas instancias son privadas, por lo que, teóricamente, no puede acceder a ellas. Sin embargo, a través de la reflexión, podemos acceder a la instancia File para eliminar estos archivos útiles pero molestos.

Los siguientes métodos permiten hacer esto. Al llamar al deleteSXSSFTempFiles, se eliminan todos los archivos temporales de ese libro de trabajo.

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