8

単一の InputStream から、ZIP 内の複数の XML ファイルを読み取るメソッドを作成したいと考えています。

このメソッドは ZipInputStream を開き、各 xml ファイルで対応する InputStream を取得し、それを XML パーサーに渡します。メソッドのスケルトンは次のとおりです。

private void readZip(InputStream is) throws IOException {

    ZipInputStream zis = new ZipInputStream(is);
    ZipEntry entry = zis.getNextEntry();

    while (entry != null) {

        if (entry.getName().endsWith(".xml")) {

            // READ THE STREAM
        }
        entry = zis.getNextEntry();
    }
}

問題の部分は「// READ THE STREAM」です。ByteArrayInputStream を作成し、それをパーサーにフィードするという実用的なソリューションがあります。しかし、それはバッファを使用し、大きなファイルの場合、OutOfMemoryError が発生します。誰かがまだ興味がある場合のコードは次のとおりです。

int count;
byte buffer[] = new byte[2048];
ByteArrayOutputStream out = new ByteArrayOutputStream();
while ((count = zis.read(buffer)) != -1) { out.write(buffer, 0, count); }       
InputStream is = new ByteArrayInputStream(out.toByteArray());

理想的な解決策は、パーサーに元の ZipInputStream を供給することです。エントリの内容を Scanner で印刷するだけで機能するため、機能するはずです。

Scanner sc = new Scanner(zis);
while (sc.hasNextLine())
{
    System.out.println(sc.nextLine());
}

しかし...私が現在使用しているパーサー(jdom2ですが、javax.xml.parsers.DocumentBuilderFactoryでも試しました)は、データの解析後にストリームを閉じます:/ . そのため、次のエントリを取得して続行することができません。

最後に質問は次のとおりです。

  • ストリームを閉じない DOM パーサーを知っている人はいますか?
  • ZipEntry から InputStream を取得する別の方法はありますか?

ありがとう。

4

3 に答える 3

4

halfbit のおかげで、close メソッドをオーバーライドする独自の ZipInputStream クラスになりました。

import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipInputStream;

public class CustomZipInputStream extends ZipInputStream {

    private boolean _canBeClosed = false;

    public CustomZipInputStream(InputStream is) {
        super(is);
    }

    @Override
    public void close() throws IOException {

        if(_canBeClosed) super.close();
    }

    public void allowToBeClosed() { _canBeClosed = true; }
}
于 2013-11-16T17:01:10.750 に答える