8

FileInputStream を開いている大きなファイルがあります。このファイルには、先頭からのオフセットとサイズを持ついくつかのファイルが含まれています。さらに、そのような含まれているファイルを評価するパーサーがあります。

File file = ...; // the big file
long offset = 1734; // a contained file's offset
long size = 256; // a contained file's size
FileInputStream fis = new FileInputStream(file );
fis.skip(offset);
parse(fis, size);

public void parse(InputStream is, long size) {
   // parse stream data and insure we don't read more than size bytes
   is.close();
}

これは良い習慣ではないように感じます。おそらくバッファリングを使用して、これを行うより良い方法はありますか?

さらに、skip() メソッドが読み取りプロセスを大幅に遅くしているように感じます。

4

5 に答える 5

6

あなたが本当に必要としているのは、一種の「部分的な」入力ストリームのようです。これは、ストリーム内にストリームがある ZipInputStream に少し似ています。

これを自分で記述して、すべての InputStream メソッドを元の入力ストリームにプロキシし、オフセットを適切に調整して、サブファイルの末尾を過ぎた読み取りをチェックすることができます。

そういう話ですか?

于 2008-12-14T19:49:38.743 に答える
3

まず、FileInputStream.skip() にはバグがあり、その下にあるファイルがファイルの EOF マーカーを超えてスキップされる可能性があるため、注意が必要です。

私は個人的に、FileReader と FileWriter を使用する場合と比較して、Input/OutputStreams を操作するのが苦痛であることに気付きました。あなたは、私が抱えている主な問題を示しています:使用後にストリームを閉じる必要があることです。問題の 1 つは、次のようにコードを慎重に作成しない限り、すべてのリソースを適切に閉じたかどうかを確認できないことです。

public void parse(File in, long size) {
    try {
        FileInputStream fis = new FileInputStream(in);
        // do file content handling here
    } finally {
        fis.close();
    }
    // do parsing here
}

もちろん、これは常に新しいオブジェクトを作成することにつながり、最終的に多くのリソースを消費する可能性があるという意味で悪いことです。もちろん、これの良い面は、ファイル処理コードが例外をスローした場合でも、ストリームが閉じられることです。

于 2008-12-14T19:59:17.350 に答える
2

これは典型的なネストされたファイル、別名「zip」ファイルの問題のようです。

これを処理する一般的な方法は、ネストされた論理ストリームごとに個別の InputStream インスタンスを実際に持つことです。これらは、基礎となる物理ストリームで必要な操作を実行し、バッファリングは、どちらが最適かによって、基礎となるストリームと論理ストリームの両方で行うことができます。これは、論理ストリームが、基になるストリーム内の配置に関するすべての情報をカプセル化することを意味します。

たとえば、次のようなシグネチャを持つ一種のファクトリ メソッドを使用できます。

List<InputStream> getStreams(File inputFile)

OutputStreams でも同じことができます。

これにはいくつかの詳細がありますが、これで十分でしょうか?

于 2008-12-14T19:48:44.390 に答える
1

一般に、ファイルを開くコードはファイルを閉じる必要があります。parse()関数は、プログラムの残りの部分が続行したくないと想定するのが非常に傲慢であるため、入力ストリームを閉じないようにする必要があります。大きなファイルに含まれている他のファイルを読み取る。

parse()のインターフェイスをストリームと長さ(ファイルが正しく配置されていると想定できる関数を使用)にするか、インターフェイスにオフセットを含める(関数が最初に配置してから読み取る)かを決定する必要があります。どちらの設計も実行可能です。parse()にポジショニングを任せたいと思いますが、それは明確な決定ではありません。

于 2008-12-14T21:38:00.473 に答える
0

RandomAccessFile でラッパー クラスを使用できます -これを試してください

それを BufferedInputStream にラップして、パフォーマンスが向上するかどうかを確認することもできます。

于 2008-12-14T19:48:55.297 に答える