web-dev-qa-db-ja.com

Java-InputStreamのリセット

私はいくつかのJavaコードを扱っています。このコードでは、一度読み取ったInputStreamがあり、同じメソッドでもう一度読み取る必要があります。

問題は、2回読むために、その位置を最初にリセットする必要があることです。

私は問題のハックっぽい解決策を見つけました:

is.mark(Integer.MAX_VALUE);

//Read the InputStream is fully
// { ... }

try
{
    is.reset();
}
catch (IOException e)
{
    e.printStackTrace();
}

この解決策は、疑わしい行動につながるのですか?それとも、それは愚かさで機能しますか?

15
iMineLink

書かれているとおり、mark()は成功したかどうかを報告する必要がないため、保証はありません。保証を得るには、最初に markSupported() を呼び出し、trueを返す必要があります。

また、書かれているように、指定された読み取り制限は非常に危険です。メモリ内でバッファリングするストリームを使用している場合、2GBのバッファが割り当てられる可能性があります。一方、FileInputStreamを使用している場合は問題ありません。

より適切な方法は、明示的なバッファでBufferedInputStreamを使用することです。

9
kdgregory

これを確実に行うことはできません。一部のInputStreams(端末やソケットに接続されているものなど)はmarkおよびresetをサポートしていません( markSupported を参照) 。データを2回トラバースする必要がある場合は、独自のバッファーに読み込む必要があります。

2
chrylis

これは、InputStreamの実装によって異なります。また、byte []を使用した方が良いかどうかを考えることもできます。最も簡単な方法は、Apache commons-io を使用することです。

byte[] bytes = IOUtils.toByteArray(inputSream);
2
stan

InputStreamをリセットしようとする代わりに、StringBuilderのようにバッファにロードするか、バイナリデータストリームの場合はByteArrayOutputStreamをロードします。その後、メソッド内のバッファを何度でも処理できます。

ByteArrayOutputStream bos = new ByteArrayOutputStream();

int read = 0;
byte[] buff = new byte[1024];
while ((read = inStream.read(buff)) != -1) {
    bos.write(buff, 0, read);
}
byte[] streamData = bos.toByteArray();
1
Ravi Thapliyal

私にとって、最も簡単な解決策は、InputStreamを取得できるオブジェクトを渡して、再度取得することでした。私の場合、それはContentResolverからのものでした。

1
androidguy