11

XLSXファイルを読み取るためXSSFにを使用しています。apache-POIエラーが発生していましjava.lang.OutOfMemoryError: Java heap spaceた。-Xmx1024mその後、 Javaクラスに使用してヒープサイズを増やしても、同じエラーが繰り返されます。

コード:

String filename = "D:\\filename.xlsx";
FileInputStream fis = null;
try {
   fis = new FileInputStream(filename);
   XSSFWorkbook workbook = new XSSFWorkbook(fis);

上記のコードセグメントでは、実行はで停止しXSSFWorkbook、指定されたエラーをスローします。誰かが大きなXLSXファイルを読み取るためのより良いアプローチを提案できますか?

4

2 に答える 2

17

POIを使用すると、Excelファイルをストリーミング方式で読み取ることができます。APIはSAXのラッパーです。文字列を受け取るコンストラクターを使用して、OPCパッケージを正しい方法で開いていることを確認してください。そうしないと、すぐにメモリが不足する可能性があります。

OPCPackage pkg = OPCPackage.open(file.getPath());
XSSFReader reader = new XSSFReader(pkg);

これで、リーダーを使用InputStreamsしてさまざまな部分を取得できるようになります。(SAXまたはStAXを使用して)自分でXML解析を実行する場合は、これらを使用できます。ただし、フォーマットに精通している必要があります。

より簡単なオプションは、XSSFSheetXMLHandlerを使用することです。最初のシートを読み取る例を次に示します。

StylesTable styles = reader.getStylesTable();
ReadOnlySharedStringsTable sharedStrings = new ReadOnlySharedStringsTable(pkg);
ContentHandler handler = new XSSFSheetXMLHandler(styles, sharedStrings, mySheetContentsHandler, true);

XMLReader parser = XMLReaderFactory.createXMLReader();
parser.setContentHandler(handler);
parser.parse(new InputSource(reader.getSheetsData().next()));

mySheetsContentHandlerは、XSSFSheetXMLHandler.SheetContentsHandlerの独自の実装である必要があります。このクラスには行とセルが供給されます。

ただし、共有文字列テーブルが巨大な場合(巨大なシートに重複する文字列がない場合に発生します)、これは適度にメモリを消費する可能性があることに注意してください。それでもメモリに問題がある場合は、生のXMLストリーム(XSSFReaderも提供)を使用することをお勧めします。

于 2012-07-05T13:56:23.213 に答える
0

@waxwingの答えを補足するために、入力XLS(X)ファイルがパスワードで保護されている場合は、元のファイルを復号化デコレータでラップして、プレーンな入力ストリームを取得する必要があります。ただし、最初に、ファイルをとして開く必要がありますPOIFSFileSystem

つまり、一言で言えば:

String pass = "secret";
File file = new File("data/1.xlsx");
    
try (POIFSFileSystem fs = new POIFSFileSystem(file);
   // wrap in org.apache.poi.poifs.filesystem.DocumentFactoryHelper.getDecryptedStream
   InputStream in = DocumentFactoryHelper.getDecryptedStream(fs, pass);
   OPCPackage pkg = OPCPackage.open(in)) 
{
    XSSFReader reader = new XSSFReader(pkg);
        
    StylesTable styles = reader.getStylesTable();
    ReadOnlySharedStringsTable sharedStrings = new ReadOnlySharedStringsTable(pkg);
    SheetContentsHandler f = new SheetContentsHandler() {
       // ... your implementation of SheetContentsHandler interface ...
    };
    ContentHandler handler = new XSSFSheetXMLHandler(styles, sharedStrings, f, true);
    XMLReader parser = XMLReaderFactory.createXMLReader();
    parser.setContentHandler(handler);
    parser.parse(new InputSource(reader.getSheetsData().next()));
}
于 2021-05-24T10:36:13.207 に答える