2012-04-13 8 views
15

私はHttpServletResponseに書きたいInputStreamを持っています。 私はおそらく速度と効率の面で、それを行うための最善の方法かもしれないと思いまして[]HttpServletResponseへのInputStreamの書き込み

InputStream is = getInputStream(); 
int contentLength = getContentLength(); 

byte[] data = new byte[contentLength]; 
is.read(data); 

//response here is the HttpServletResponse object 
response.setContentLength(contentLength); 
response.write(data); 

によるバイトの使用に時間がかかりすぎる、このアプローチは、あります。

答えて

41

Javaのメモリに完全にコピーするのではなく、ブロックで書き込んでください。以下の基本的な例では、それを10KB単位で書き込みます。この方法では、完全なコンテンツ長ではなく、わずか10KBの一貫したメモリ使用量になります。また、エンドユーザは、コンテンツの一部をずっと早く取得し始めます。パフォーマンスに関してクレームデラクレームとして

response.setContentLength(getContentLength()); 
byte[] buffer = new byte[10240]; 

try (
    InputStream input = getInputStream(); 
    OutputStream output = response.getOutputStream(); 
) { 
    for (int length = 0; (length = input.read(buffer)) > 0;) { 
     output.write(buffer, 0, length); 
    } 
} 

、あなたはNIO Channelsを使用することができますし、直接ByteBufferを割り当てられました。いくつかのカスタムユーティリティクラスで、次のユーティリティ/ヘルパーメソッドを作成します。 Utils:あなたは以下のように使用し

public static long stream(InputStream input, OutputStream output) throws IOException { 
    try (
     ReadableByteChannel inputChannel = Channels.newChannel(input); 
     WritableByteChannel outputChannel = Channels.newChannel(output); 
    ) { 
     ByteBuffer buffer = ByteBuffer.allocateDirect(10240); 
     long size = 0; 

     while (inputChannel.read(buffer) != -1) { 
      buffer.flip(); 
      size += outputChannel.write(buffer); 
      buffer.clear(); 
     } 

     return size; 
    } 
} 

response.setContentLength(getContentLength()); 
Utils.stream(getInputStream(), response.getOutputStream()); 
+0

私はそこに別の方法があることを望んでいましたが、とにかく感謝します –

+0

ありがとうございます。BalusC、 –

+2

もちろん、多くのユーティリティパッケージにはこのメソッドが既に定義されていますので、Guavaを使用し始めるとhttp://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/io /ByteStreams.html#copy(java.io.InputStream、java.io.OutputStream) –

1
BufferedInputStream in = null; 
BufferedOutputStream out = null; 
OutputStream os; 
os = new BufferedOutputStream(response.getOutputStream()); 
in = new BufferedInputStream(new FileInputStream(file)); 
out = new BufferedOutputStream(os); 
byte[] buffer = new byte[1024 * 8]; 
int j = -1; 
while ((j = in.read(buffer)) != -1) { 
    out.write(buffer, 0, j); 
} 
+0

を、私は、バイト[]の使用を避けるために、ワン可能 –

+0

はワット使用してO/InputStreamを読んでする方法はありません@MuhammadSabry場合 ' byte [] ' –

+0

byte []の何が問題ですか。あなたはデータをどこかに保存する必要があります:} – MTilsted

0

私はそれが最良の方法に非常に近いと思いますが、私は以下の変更を提案します。固定サイズのバッファを使用して(20Kと言う)、読み書きをループします。読み取りは、常にあなたがそれを与える配列全体を埋めていないので、あなたのプログラムは、常にそのまま動作しません:Forループ

Byte buffer[]=new byte[20*1024]; 
outputStream=response.getOutputStream(); 
while(true) { 
    int readSize=is.read(buffer); 
    if(readSize==-1) 
    break; 
    outputStream.write(buffer,0,readSize); 
} 

psのような何かを行います。

+0

あなたが読んだことは、あなたがそれを与える配列全体をいっぱいに埋めるわけではないのですか? –

+1

読み取りが必ずしも入力配列をいっぱいにするとは限りません。だから、読み込みバイト数である読み込み戻り値をチェックする必要があります。 (http://docs.oracle.com/javase/6/docs/api/java/io/InputStream.html#read%28byte[]%29) – MTilsted

関連する問題