2012-04-13 29 views
15

HttpServletResponse'ye yazılmasını istediğim bir InputStream var. çok uzun sürüyor bu yaklaşım nedeniyle byte kullanımına var []Bir HttpServletResponse'ye bir giriş akışı yazın

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); 

muhtemelen hız ve verimlilik açısından, bunu yapmanın en iyi yolu ne olabilir merak ediyorum.

cevap

41

Öncelikle tamamen Java'nın belleğine kopyalamak yerine blok halinde yazınız. Aşağıdaki temel örnek, 10 KB'lik bloklara yazar. Bu sayede, tam içerik uzunluğu yerine sadece 10 KB tutarlı bir bellek kullanımıyla sonuçlanırsınız. Ayrıca, son kullanıcı, içeriğin bir kısmını daha çabuk almaya başlayacaktır. performans açısından

creme de la creme olarak

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); 
    } 
} 
, sen MİT Channels kullanabilir ve bir doğrudan ByteBuffer ayırdı. Bazı özel yardımcı program sınıflarında aşağıdaki yardımcı programı/yardımcı yöntemi oluşturun, ör. Utils: o zaman aşağıdaki gibi kullanmak

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

Başka bir yol olabileceğini umuyordum, ama yine de teşekkürler –

+0

Teşekkürler BalusC, –

+2

Tabii ki birçok yardımcı program, bu yöntemi zaten tanımlıyor, bu yüzden Guava'yı kullanmaya başladığınızda ... 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

ben byte [] kullanımını önlemek için wan mümkün –

+0

w kullanarak o/InputStream okumak için hiçbir yolu yoktur @MuhammadSabry eğer ' byte [] ' –

+0

Bayt [] ile ilgili sorun nedir? Verileri bir yere saklamanız gerekir:} – MTilsted

0

Bu, en iyi yönteme çok yakın olduğunu düşünüyorum, ancak aşağıdaki değişikliği öneririm. Sabit boyutlu bir tampon kullanın (20K Say) ve ardından okuma/yazma işlemini bir döngüde yapın. Okuma her zaman verin dizinin tamamı dolmaya yok çünkü, Programınız her zaman olduğu gibi çalışmaz: For döngüsü

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 böyle bir şey yapmak.

+0

Tam olarak ne demek demek, okuduğunuz diziyi tam olarak doldurmuyor mu? –

+1

Okuma, her zaman giriş dizisini doldurmaz. Bu yüzden okunan bayt sayısı olan okunan değeri kontrol etmeniz gerekir. (Bkz. Http://docs.oracle.com/javase/6/docs/api/java/io/InputStream.html#read%28byte[]%29) – MTilsted

İlgili konular