7

以下のプログラムを実行しようとすると、java.lang.OutOfMemoryError: GC オーバーヘッド制限を超えましたという例外が発生します。このプログラムのメイン メソッドは、指定されたディレクトリにアクセスし、.xlsx を含むすべてのファイルを反復処理します。他のロジックの前にテストしたので、これは正常に機能します。また、基本的にxlsxファイルをcsvに変換して既存のファイルに追加するxlsxを呼び出すメソッドも正常に機能します。しかし、それを for ループに入れると、この例外が発生します。xlsxを開いてcsvに変換した後、2番目を開くときに競合があると推測しています。おそらく、この行を閉じる必要があります。

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

これは、ループの 2 回目の繰り返しが発生したときに、このファイルが干渉しているときに発生するという私の唯一の推測です。Excel ファイルを操作するために Apache POI ライブラリを使用しています。前もって感謝します!

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();
            }
        }



}

追加情報:

以下はスタックトレースです

   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)

Excel ファイルはかなり大きく、ディレクトリには約 30 個ほどあり、最大のものは約 170 MB です。これらのファイル サイズを POI から変更する必要がありますか?

4

2 に答える 2

3

エクセルファイルのサイズは?csvから作成して、同様の問題が一度ありましたxls。私の場合、イベント駆動モデルに切り替える必要がありました。XSSF と SAX (Event API) を見てください。私もメモリ不足です (with -Xmx8g)

リンク先サイトからの引用:

HSSF に関するさらなる取り組みは、次の主要な分野に焦点を当てる予定です。

  • パフォーマンス: 現在、POI は大きなシートに大量のメモリを使用しています。
于 2013-10-17T19:45:12.313 に答える
1

ファイルを閉じる必要はありません。それらへの参照を維持していない限り、それらは範囲外になるためGCdされます。

if (i != 0)この条件に到達する前に変数 i を少なくとも 1 回インクリメントしているため、この行は常に true と評価されます。したがって、firstSheet は常に false に設定されます。

この線

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

新しいファイルを作成しています。ただし、で表されるこのパスのファイル オブジェクトが既にあります。child

すべての書き込みが同じファイルに対するものであっても、最初のディレクトリの子を反復処理するたびに、ファイルオブジェクトと新しい FileOutputStream を再作成する同じファイルに常に書き込みます。

最終ブロックで FileOutputStream を閉じていないため、エラー状態で FileOutputStream を適切に閉じていない可能性があります。

文字列を構築するための同期メソッドが必要でない限り、StringBuffer の代わりに StringBuilder を使用します。

中間の StringBuilder の代わりに FileWriter を使用することを検討してください。Builder に書き込む代わりに、

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

data.appenduse writer.printorの代わりにwriter.println注: PrintWriter および Buffered Writer ラッパーは厳密には必要ではありませんが、便利です。

コンストラクターのオプションについて XSSFWorkbook の javadoc を参照すると、「InputStream を使用すると、ファイルを使用するよりも多くのメモリが必要になるため、ファイルが使用可能な場合は、代わりに「次の例」のようなことを行う必要があります」と表示されます http:// poi.apache.org/apidocs/org/apache/poi/xssf/usermodel/XSSFWorkbook.html#XSSFWorkbook(java.io.InputStream)

他のすべてが失敗した場合は、ヒープ サイズを増やすことが実行可能な解決策になる可能性があります。現在テストしているファイルよりも大幅に大きなファイルになる可能性はないと仮定します。Java でヒープ サイズを増やす

于 2013-10-17T20:47:33.887 に答える