开发者

Most effective way to write File to ServletOutputStream

ServletOutputStream output = response.getOutputStream();
output.write(byte[]);

What is the most effective 开发者_JAVA技巧way to write File to javax.servlet.ServletOutputStream?

EDIT:

won't this be more effective if the NIO was used?


IOUtils.copy(in, out);
out.flush();
//...........
out.close(); // depends on your application

Where in is the FileInputStream and out is the SocketOutputStream. IOUtils is a utility from Commons IO module in Apache Commons.


You have a ServletOutputStream. The only way you can write to that is via java.io.*. You can't use NIO on it at all (other than via wrapping with Channels, which is pointless: it's still an OutputStream underneath and you are just adding processing over the top). The actual I/O is network-bound, and your writes are being buffered anyway by the servlet container (so that it can set the Content-Length) header so looking for performance tweaks here is pointless.


First of all, this is unrelated to servlets. This applies to Java IO in general. You have after all just an InputStream and an OutputStream.

As to the answer, you're not the only one who wondered about this. On the interwebs you can find others who wondered about the same but took the effort to test/benchmark it themselves:

  • Java tip: How to read files quickly?
  • File copy in Java - Benchmark

In general, a FileChannel with a 256K byte array which is read through a wrapped ByteBuffer and written directly from the byte array is the fastest way. Indeed, NIO.

FileInputStream input = new FileInputStream("/path/to/file.ext");
FileChannel channel = input.getChannel();
byte[] buffer = new byte[256 * 1024];
ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);

try {
    for (int length = 0; (length = channel.read(byteBuffer)) != -1;) {
        System.out.write(buffer, 0, length);
        byteBuffer.clear();
    }
} finally {
    input.close();
}


If you don't want to add that jar to your application then you have to copy it by hand. Just copy the method implementation from here: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/main/java/org/apache/commons/io/IOUtils.java?revision=1004358&view=markup:

private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;

public static int copy(InputStream input, OutputStream output) throws IOException {
  long count = copyLarge(input, output);
  if (count > Integer.MAX_VALUE) {
    return -1;
  }
  return (int) count;
}

public static long copyLarge(InputStream input, OutputStream output)
    throws IOException {
   byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
   long count = 0;
   int n = 0;
   while (-1 != (n = input.read(buffer))) {
     output.write(buffer, 0, n);
     count += n;
   }
   return count;
}

put those 2 methods in one of your helper classes and you're good to go.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜