2013-10-17 14 views
7

Bir java.lang.OutOfMemoryError hatası alıyorum: Aşağıdaki programı çalıştırmaya çalıştığımda GC overhead sınırı istisnayı aştı. Bu programın ana yöntemi 'belirtilen bir dizine erişir ve .xlsx içeren tüm dosyaları yineler. Bu, diğer mantıklardan önce test ettiğim gibi iyi çalışıyor. Ve xlsx dosyasını temel olarak csv'ye dönüştüren ve varolan bir dosyaya ekleyen xlsx yöntemi de iyi çalışıyor. Ama bunu for döngüsüne koyduğumda, bu istisnayı aldığım zamandır. Benim tek tahmin şimdi Thatsjava.lang.OutOfMemoryError: GC overhead limiti excel okuyucusunu aştı

File inputFile = new File("C:\\Users\\edennis.AD\\Desktop\\test\\"+nameOfFile); 

: Ben xlsx açtı sonra bir tutarsızlık olması onu tahmin ve ona csv ve belki ben bir şekilde bu çizgiyi kapatmak zorunda ikinci açmayı zaman dönüştürülür am Bu dosya, döngü ikinci iterasyonuna girdiğinde müdahale ediyor. Excel dosyalarını işlemek için Apache POI kitaplıklarını kullanıyorum. Şimdiden teşekkürler!

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import org.apache.poi.ss.usermodel.Cell; 
import org.apache.poi.ss.usermodel.Row; 
import org.apache.poi.xssf.usermodel.XSSFSheet; 
import org.apache.poi.xssf.usermodel.XSSFWorkbook; 

public class ExcelMan { 

    public static void main(String[] args) throws FileNotFoundException { 



     int i =0; 


      File dir = new File("C:\\Users\\edennis.AD\\Desktop\\test\\"); 
      for (File child : dir.listFiles()) { 

      //initializing whether the sheet sent to method is first or not, and //counting iterations for each time the for loop as run 

      boolean firstSheet = true; 
      i++; 

      String nameOfFile = child.getName(); 

      if (nameOfFile.contains(".xlsx")){ 

      System.out.println(nameOfFile); 

       if (i != 0) 
       firstSheet = false; 


       File inputFile = new File("C:\\Users\\edennis.AD\\Desktop\\test\\"+nameOfFile); 

       // writing excel data to csv 
       File outputFile = new File("C:\\Users\\edennis.AD\\Desktop\\test\\memb.csv"); 
       xlsx(inputFile, outputFile, firstSheet); 


      } 


      // } 

     } 


    } 




     static void xlsx(File inputFile, File outputFile, boolean firstSheet) { 
      // For storing data into CSV files 
      StringBuffer data = new StringBuffer(); 


      try { 
       FileOutputStream fos = new FileOutputStream(outputFile, true); 
       // Get the workbook object for XLSX file 
       XSSFWorkbook wBook = new XSSFWorkbook(new FileInputStream(inputFile)); 
       // Get first sheet from the workbook 


       XSSFSheet sheet = wBook.getSheetAt(7); 
       Row row; 
       Cell cell; 
       // Iterate through each rows from first sheet 
       java.util.Iterator<Row> rowIterator = sheet.iterator(); 

       while (rowIterator.hasNext()) { 

        if (firstSheet != true) 
         rowIterator.next(); 

        row = rowIterator.next(); 

        // For each row, iterate through each columns 
        java.util.Iterator<Cell> cellIterator = row.cellIterator(); 
        while (cellIterator.hasNext()) { 


         cell = cellIterator.next(); 

         switch (cell.getCellType()) { 
          case Cell.CELL_TYPE_BOOLEAN: 
           data.append(cell.getBooleanCellValue() + "^"); 

           break; 
          case Cell.CELL_TYPE_NUMERIC: 
           data.append(cell.getNumericCellValue() + "^"); 

           break; 
          case Cell.CELL_TYPE_STRING: 
           data.append(cell.getStringCellValue() + "^"); 
           break;        
          case Cell.CELL_TYPE_BLANK: 
           data.append("" + "^"); 
           break; 
          default: 
           data.append(cell + "^"); 

         } 


        } 
        data.append("\r\n"); 

       } 

       fos.write(data.toString().getBytes()); 
       fos.close(); 


      } catch (Exception ioe) { 
       ioe.printStackTrace(); 
      } 
     } 



} 

Ek Bilgi: Aşağıda

orada yaklaşık 30 ya da öylesine dizinde ve en büyük birinde yaklaşık olacak, excel dosyaları oldukça büyük

MR.xlsx 
    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 
     at org.apache.xmlbeans.impl.store.Cur$CurLoadContext.attr(Cur.java:3039) 
     at org.apache.xmlbeans.impl.store.Cur$CurLoadContext.attr(Cur.java:3060) 
     at org.apache.xmlbeans.impl.store.Locale$SaxHandler.startElement(Locale.java:3250) 
     at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.reportStartTag(Piccolo.java:1082) 
     at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseAttributesNS(PiccoloLexer.java:1802) 
     at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseOpenTagNS(PiccoloLexer.java:1521) 
     at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseTagNS(PiccoloLexer.java:1362) 
     at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseXMLNS(PiccoloLexer.java:1293) 
     at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseXML(PiccoloLexer.java:1261) 
     at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.yylex(PiccoloLexer.java:4808) 
     at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.yylex(Piccolo.java:1290) 
     at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.yyparse(Piccolo.java:1400) 
     at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.parse(Piccolo.java:714) 
     at org.apache.xmlbeans.impl.store.Locale$SaxLoader.load(Locale.java:3439) 
     at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:1270) 
     at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:1257) 
     at org.apache.xmlbeans.impl.schema.SchemaTypeLoaderBase.parse(SchemaTypeLoaderBase.java:345) 
     at org.openxmlformats.schemas.spreadsheetml.x2006.main.WorksheetDocument$Factory.parse(Unknown Source) 
     at org.apache.poi.xssf.usermodel.XSSFSheet.read(XSSFSheet.java:138) 
     at org.apache.poi.xssf.usermodel.XSSFSheet.onDocumentRead(XSSFSheet.java:130) 
     at org.apache.poi.xssf.usermodel.XSSFWorkbook.onDocumentRead(XSSFWorkbook.java:286) 
     at org.apache.poi.POIXMLDocument.load(POIXMLDocument.java:159) 
     at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(XSSFWorkbook.java:207) 
     at ExcelMan.xlsx(ExcelMan.java:71) 
     at ExcelMan.main(ExcelMan.java:47) 

StackTrace olduğunu 170 MB, bu dosya boyutları ile POI'den değiştirmeliyim?

+0

Tüm yığın izini ekleyebilir misiniz? – fvrghl

+3

java yığınını artırmalısınız. http://stackoverflow.com/questions/1098488/jvm-heap-parameters –

+1

Olayla yönetilen modele geçmeniz gerekecektir, o anda kullandığınız API ile büyük dosyaları işleyemezsiniz. –

cevap

3

Excel dosyanızın boyutu nedir? Benzer bir problemim vardı, csv'u xls'dan yarattım. Benim durumumda event driven model'a geçmek zorunda kaldım, XSSF ve SAX (Olay API)'a bakın.

Further effort on HSSF is going to focus on the following major areas:

  • Performance: POI currently uses a lot of memory for large sheets.
+0

Excel dosyalarınız ne kadar büyüktü? OP umarım 4GB RAM kullanarak 170MB dosyaları ile ilgilenmek gerekir ... Umarım doğru boyutta dosyaları hatırlıyorum eğer umarım ... – nneonneo

+0

@nneonneo. Daha sonra deneyebilirim, belki de etrafta yatan dosyalardan birine sahibim. –

1

Dosyalar kapalı olması gerekmez: Ben de

(-Xmx8g birlikte) bellek yetersiz bağlantılı alana sadece alıntı koştu. Onlara referans göstermediğiniz sürece, kapsam dışında kaldıklarında GCd olacaktır.

if (i != 0) hattı her zaman doğru olarak değerlendirecektir, çünkü bu koşulu yerine getirmeden önce en az bir kez değişkeninizi artırıyorsunuz. Böylece birinci sayfa her zaman yanlış olarak ayarlanır.

hat

File inputFile = new File("C:\\Users\\edennis.AD\\Desktop\\test\\"+nameOfFile); 

yeni dosyalar yaratıyor. Ancak, bu yol için zaten child

tarafından temsil edilen bir dosya nesnesiniz var. Her zaman olsa bile, ilk dizinler üzerinde yinelediğiniz her zaman bir dosya nesnesi ve yeni FileOutputStream yeniden oluşturduğunuz aynı dosyaya yazıyorsunuz. yazarlar aynı dosyaya.

FileOutputStream'inizi son olarak bir blokta kapatmıyorsunuz ve FileOutputStream'inizi hata koşullarına uygun şekilde kapatmıyor olabilirsiniz.

Dizeyi oluşturmak için senkronize yöntemlere gerek duymadıkça StringBuffer yerine StringBuilder kullanın.

Arabirim StringBuilder yerine bir FileWriter kullanmayı düşünün.Bunun yerine bir Builder yazma yerine data.append kullanacağım writer.print veya writer.println Not yapmanın

PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(outputFile, true)))) 

kullanın: PrintWriter ve Tamponlu Yazar sargılar kesinlikle gerekli, ama yararlı değildir.

Kurucular için XSSFWorkbook javadocs seçeneklerine başvurursanız, göreceksiniz ki "Bir InputStream kullanmak bir Dosya kullanmaktan daha fazla bellek gerektirir, bu nedenle bir Dosya varsa, bunun yerine" örnek izler "gibi bir şey yapmalısınız. http://poi.apache.org/apidocs/org/apache/poi/xssf/usermodel/XSSFWorkbook.html#XSSFWorkbook(java.io.InputStream)

Diğerlerinin başarısız olması durumunda yığın boyutunuzu arttırmak muhtemelen uygulanabilir bir çözüm olacaktır. Şu anda test ettiğinizden çok daha büyük dosyalar için potansiyeliniz olmadığını varsayarak. Increase heap size in Java

İlgili konular