2012-08-13 12 views
5

私はHttpServletRequest(以下の '要求')からのリクエストストリーム(gzippedデータを含む)を読み込むために何かを書いていますが、通常のInputStream読み込みメソッドは実際にすべてのコンテンツを読み取っていないようです。InputStream.read(byte []、0 length)は早期に停止しますか?

私のコードだった:私はテスト中に見つけたもの

InputStream requestStream = request.getInputStream(); 
if ((length = request.getContentLength()) != -1) 
{ 
    received = new byte[length]; 
    requestStream.read(received, 0, length); 
} 
else 
{ 
    // create a variable length list of bytes 
    List<Byte> bytes = new ArrayList<Byte>(); 

    boolean endLoop = false; 
    while (!endLoop) 
    { 
     // try and read the next value from the stream.. if not -1, add it to the list as a byte. if 
     // it is, we've reached the end. 
     int currentByte = requestStream.read(); 
     if (currentByte != -1) 
      bytes.add((byte) currentByte); 
     else 
      endLoop = true; 
    } 
    // initialize the final byte[] to the right length and add each byte into it in the right order. 
    received = new byte[bytes.size()]; 
    for (int i = 0; i < bytes.size(); i++) 
    { 
     received[i] = bytes.get(i); 
    } 
} 

は時々(コンテンツの長さが存在する場合のために)上部だけで、着信要求ストリームの途中で読むのをやめ、残りを残すことでした「受信した」バイト配列の空白。 if文のelse部分を常に実行させると、それは正常に読み込まれ、すべての予期されたバイトは 'received'に置かれます。

だから、私はちょうどその変更になりました一人で自分のコードを残すことができますように思えるが、誰もが通常の「読み取り」(バイト[]、int型、int型)」メソッドが読んで停止した理由の任意のアイデアを持っているのですか?この説明には、ファイルの終わりがある場合には停止することがあります。 gzipされたデータがちょうどそのようなものの署名にマッチするバイトを含んでいた可能性はありますか?

+0

ところで、あなたは(http://docs.oracle.com/javase/7/docs/api/java/util/zip/GZIPInputStream.html)[GZIPInputStream]を見てみたいことがあります。すべてをバイト配列に読み込んだ後、別々にデータを解凍するのではなく、生のInputStreamをGZIPInputStreamにラップして、解凍されたデータを直接読み取ることができます。 –

+0

ああ、私たちが直接それをしない理由は、他のシステムから受け取った入力が実際にはgzipされていなくても... ... –

答えて

8

あなたはすべてのバイトを取得するために先頭にwhileループを追加する必要があります。ストリームは、それができる限り多くのバイトを読み込むしようとしますが、一度にlenバイトを返すために必要されていません。

試みがlenバイト限り多くを読むために作られているが、より小さい数は読み取ることができますおそらくゼロ。

if ((length = request.getContentLength()) != -1) 
{ 
    received = new byte[length]; 
    int pos = 0; 
    do { 
     int read = requestStream.read(received, pos, length-pos); 

     // check for end of file or error 
     if (read == -1) { 
      break; 
     } else { 
      pos += read; 
     } 
    } while (pos < length); 
} 

EDIT:固定しばらく。

+0

ああ、それはすばらしい、ありがとう!ちなみに –

+1

、あなたは本当にデータを読むために要求の長さを使用すべきではありません。 read()メソッドは、入力の終わりに達すると-1を返します。これは、データが枯渇しているかどうかを示す目印になります。 – Matt

1

バッファの容量を確認する必要があります。それは少なくとも1バイトであなたに与えることが保証されています。

おそらく、あなたはDataInputStream.readFully()だった望ん。

+0

はい、私は他の投稿のコメントを見ましたこの問題について - それはおそらく私のためにも働くでしょうが、これを修正している間は、出力を読む方法のほうが賢明に思えました:)唯一のことは、組み込みメソッドよりも遅くなるかどうかわかりません...私たちは短い(20kまでの多分?)着信要求を期待しているにすぎませんが、おそらくそれは問題ではありません。 'read'メソッドの出力は、実際に読み取った量の点で正しいです。つまり、11kバイトの入力では、7kバイトしか読み取れないということです。なぜ私はそれをしたのか分かりません! –

+2

これは多くのデータをすぐに利用できるようにするため、さらに処理する前に処理することができます。これは、データが非常に大きい場合にespを処理する前にすべてのデータを最初に待つよりも効率的です。 –

関連する問題