2016-04-02 8 views
1

私たちはラボでいくつかの演習を行いました。そのうちの1つは、ファイル転送方法をFileInputStreamからBufferedInputStreamに変換することです。これは、要求されたファイルを送信するWebサーバーにGET要求を送信するクライアントです。 私は簡単な解決策を思いつきましたが、それが正しいかどうかをチェックしたかっただけです。FileInputStreamからBufferedInputStreamへの変換

オリジナルコード:

try { 
     FileInputStream fis = new FileInputStream(req); 
     // req, String containing file name 
     byte[] data = new byte [fis.available()]; 
     fis.read(data); 
     out.write(data); // OutputStream out = socket.getOutputStream(); 
    } catch (FileNotFoundException e){ 
     new PrintStream(out).println("404 Not Found"); 
    } 

私の試み:

try { 
     BufferedInputStream bis = new BufferedInputStream (new FileInputStream(req)); 
     byte[] data = new byte[4]; 

     while(bis.read(data) > -1) { 
     out.write(data); 
     data = new byte[4]; 
     } 
    } catch (FileNotFoundException e){ 
     new PrintStream(out).println("404 Not Found"); 
    } 

ファイルは、単純なHTMLページが含まれていたindex.htmlという名前のWebページが、あります。 ファイルの倍数が4の倍数でない場合、whileループの最後の実行時にデータ配列に前回の実行時の文字が含まれているため、毎回配列を再割り当てする必要があります。これはブラウザに表示されます。 デバッグの目的でデータサイズとして4を選択しました。 出力が正しいです。

これは良い解決策ですか、それとも良くできますか?

答えて

1

毎回バイト配列を再作成する必要はありません。上書きするだけです。しかし、もっと重要なことに、ループ内に概念的な誤りがあります。すべての反復は、配列がすべて有効であると仮定してストリームに書き込みます。 BufferedInputStream#readのドキュメントを調べると、配列全体を満たすのに十分なデータが読み込まれず、実際に読み取られたバイト数が返されることがわかります。この数字を使用して、書き込むバイト数を制限する必要があります。

while((int len = bis.read(data)) > -1) { 
    out.write(data, 0, len); 
} 
0

完了したら、ファイルを閉じることをお勧めします。 BufferedInputStreamは、デフォルトでは8 KBのバッファを使用し、これをより小さなバッファに縮小します。一度に8KBをコピーし、追加されたバッファを使用しないでください。

try (InputStream in = new FileInputStream(req)) { 
    byte[] data = new byte[8 << 10]; 
    for (int len; (len = bis.read(data)) > -1;) 
     out.write(data, 0, len); 
} catch (IOException e) { 
    out.write("404 Not Found\n".getBytes()); 
} 
+0

返信ありがとうございます。 hdに格納されたファイルの場合、FileInputStreamはすべての読み取り操作でディスクにアクセスしますが、BufferedInputStreamは一般的にはより効率的になります。ファイルがネットワーク経由で提供される場合も同じですか?これは私の場合ですか?または、基本的に違いはありませんか? –

+0

FileInputStreamはすべての読み取りでOSにアクセスします.OSは予測的に先読みを使用することができ、たびに頻繁にディスクにヒットします。 BufferedInputStreamは、読み込んだデータのブロックが非常に小さい場合にのみ役立ちます。 << 512バイト、読み込むバッファよりも。すなわち、魔法ではなく、より大きなバッファを読み取ることによって、あなたがすでにやっていることをやっているだけです。 –