2012-10-03 24 views
8

Używam API POI Apache do zapisywania plików XLSX. Ponieważ muszę pisać duże pliki, używam Streaming API (SXSSF). Aby to zrobić, podążam za przewodnikiem this. Zauważ, że na końcu przykładu jest wywołanie doApache POI: SXSSFWorkbook.dispose() nie istnieje

wb.dispose 

Ta instancja wb odnosi się do instancji SXSSFWorkbook. Używam tego samego w moim kodzie, ale narzeka, że ​​metoda dispose nie istnieje. Pobrałem kod źródłowy i nie ma tam metody. Jednak zamiar ich SVN i sprawdzenie tej klasy kod widzimy metodę tam:

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

Próbowałem już do rekompilacji ich kodu, ale pojawia się wiele błędów ...

+0

Dlaczego nie kasa cały codebase z SVN i zbudować że z mrówki? Lub pobrać ostatnią nocną kompilację? – Gagravarr

+0

@Gagravarr Obecna wersja to 3.9-beta1 i naprawdę chciałem uniknąć używania API beta dla klientów ... –

+0

Jeśli chcesz korzystać z nowych funkcji, musisz użyć nowych wydań ... – Gagravarr

Odpowiedz

7

Począwszy od 2012-12-03, POI 3.9 jest dostępne jako stabilne wydanie. Metoda dispose() jest dostępna w tej wersji w wersji SXSSFWorkbook.

(Oczywiście, to nie był przypadek, gdy padło pytanie.)

12

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 
      } 
     } 
    } 
} 
Powiązane problemy