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.
精彩评论