3

Excelファイル(xlsx)からデータを読み取るWebアプリケーションを開発しています。私はExcelシートを読むためにPOIを使用しています。問題は、Excelファイルを読み込もうとすると、サーバーが次のエラーをスローすることです。

ここに画像の説明を入力してください

私が読み込もうとしているExcelファイルのサイズは約80MBです。この問題の解決策はありますか?

実際、ユーザーはファイルをディスクに保存した後、ファイルとアプリケーションをアップロードしています。ファイルを読み取ろうとします。テストに使用しているコードスニペットは次のとおりです。

 File savedFile = new File(file_path);

FileInputStream fis = null;
            try {

                fis = new FileInputStream(savedFile);
                XSSFWorkbook xWorkbook = new XSSFWorkbook(fis);
                XSSFSheet xSheet = xWorkbook.getSheetAt(5);

                Iterator rows = xSheet.rowIterator();
                while (rows.hasNext()) {
                    XSSFRow row = (XSSFRow) rows.next();
                    Iterator cells = row.cellIterator();

                    List data = new ArrayList();
                    while (cells.hasNext()) {
                        XSSFCell cell = (XSSFCell) cells.next();
                        System.out.println(cell.getStringCellValue());
                        data.add(cell);
                    }

                }
            } catch (IOException e) {
                e.printStackTrace();
            } 
4

7 に答える 7

3

小さな違いを生む1つのことは、最初にファイルを開くときです。ファイルがある場合は、それを渡してください。InputStreamを使用するには、すべてをメモリにバッファリングする必要があり、スペースを消費します。そのバッファリングを行う必要はないので、しないでください!

最新のナイトリービルドのPOIを実行している場合は、非常に簡単です。コードは次のようになります。

File file = new File(file_path);
OPCPackage opcPackage = OPCPackage.open(file);
XSSFWorkbook workbook = new XSSFWorkbook(opcPackage);

それ以外は、非常によく似ています。

File file = new File(file_path);
OPCPackage opcPackage = OPCPackage.open(file.getAbsolutePath());
XSSFWorkbook workbook = new XSSFWorkbook(opcPackage);

それはあなたに少しのメモリを解放するでしょう、それは十分かもしれません。そうでない場合、およびJavaヒープスペースを十分に増やすことができない場合は、XSSFUserModelの使用を停止する必要があります。

現在使用している使いやすいUserModelに加えて、POIはファイルを処理するための低レベルの方法もサポートしています。この低レベルの方法は、ファイル全体をメモリに必要とするさまざまなヘルパーがないため、使用が難しくなります。ただし、ファイルをストリーミング方式で処理するため、メモリ効率が大幅に向上します。開始するには、POI WebサイトのXSSFおよびSAX(イベントAPI)のハウツーセクションを参照してください。それを試してみて、さまざまな例も見てください。

于 2012-06-20T23:52:50.077 に答える
2

おそらく、JVMの設定を変更する必要があります。-Xmx1024 -Xms1024ランチャーに追加してみてください。

于 2012-06-20T11:43:29.863 に答える
1

Javaヒープサイズを増やすことを試みることができます。

于 2012-06-20T11:43:15.403 に答える
1

ヒープのサイズを大きくする必要があると思います。catalina.batファイルを編集することでそれを行うことができます。変数に追加-Xms1024m -Xmx1024mCATALINA_OPTSます。

  • Xms=初期Javaヒープサイズ
  • Xmx=最大Javaヒープサイズ

編集:Catalina.batから


rem   CATALINA_OPTS   (Optional) Java runtime options used when the "start",
rem                   "run" or "debug" command is executed.
rem                   Include here and not in JAVA_OPTS all options, that should
rem                   only be used by Tomcat itself, not by the stop process,
rem                   the version command etc.
rem                   Examples are heap size, GC logging, JMX ports etc.

于 2012-06-20T11:44:01.987 に答える
0

実装を変更することで問題を解決しました。実際、最初はExcelファイルからすべてのデータをフェッチしていて、データはArrayList型で格納されていました。その後、DBにデータを挿入していましたが、それが本当の問題でした。現在、私はデータをまったく保存していません。ResultSetから1つのレコードを取得したら、それをarraylistに格納するのではなく、すぐにDBに挿入します。私はこれを1つずつ挿入するのは良いアプローチではないことを知っていますが、当面はこのアプローチを使用しています。将来、もっと良いものを見つけたら、間違いなくそれに切り替えます。ありがとうございます。

于 2012-06-22T14:23:03.553 に答える
0

現在のアプローチの改善は、Excelから約100行を読み取り(最適値を取得するためにこの図を試してみてください)、データベースでバッチ更新を行うことです。これはより高速になります。

また、コードでいくつかの最適化を実行し、リストの作成を外側のループ(行データを読み取るためのループ)から移動することもできます。

リストデータ=newArrayList();

文字列バッファ(「コンマ」で区切られている可能性があります)の行にあるすべてのセルの内容を読み取り、それを配列リスト「データ」に追加します

タイプのオブジェクトをXSSFRowarraylistに追加しています。エクセルセルのオブジェクト全体を保存しても意味がありません。その内容を取り出して、オブジェクトを破棄します。

後でコンテンツをデータベースに挿入する前に、区切られたセルのコンテンツを分割して挿入を実行できます。

お役に立てれば!

于 2013-10-29T21:17:45.710 に答える
-1

それらをファイルに保存し、最後にデータベースにロードしてみてください。これにより、単一の挿入が回避されます

于 2013-09-25T10:42:48.290 に答える