Most effective way to write File to ServletOutputStream
Solution 1
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.
Solution 2
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.
Solution 3
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:
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();
}
IAdapter
Updated on August 12, 2020Comments
-
IAdapter over 3 years
ServletOutputStream output = response.getOutputStream(); output.write(byte[]);
What is the most effective way to write File to javax.servlet.ServletOutputStream?
EDIT:
won't this be more effective if the NIO was used?
-
Bozho over 13 years+1, but two notes - it's "apache commons", and you can use
IOUtils.closeQuitely(..)
-
Sean Patrick Floyd over 13 years@Bozho it used to be called Jakarta Commons many years ago :-)
-
IAdapter over 13 yearsthat doesn't work for me, I don't want to add Commons IO jar just for that functionality.
-
IAdapter over 13 yearswon't this be more effective if the NIO was used?
-
IAdapter over 13 yearswon't this be more effective if the NIO was used?
-
Mihai Toader over 13 yearsi had mixed results with nio :). It might be better or it might not. The code is definitely a little more complex and you really need to test the results on your machine to make sure is good enough. Look here for some code: thomaswabner.wordpress.com/2007/10/09/…
-
Bozho over 13 years@01 adding a dependency on apache commons rarely has any downsides ;)
-
IAdapter over 13 yearsBozho it has a very huge downside, i will have to fight with my boss, because of it. i rather reinvent the wheel than fight with him.
-
AngerClown over 13 yearsThe first link actually seems to recommend an 8K buffer since the time to copy difference between 8 and 256K is minimal. That seems to make sense given that most file systems still use 4KB pages and 4KB disk clusters.
-
BalusC over 13 yearsDifference is indeed minimal. OP is however asking for "effective way" not "efficient way". 8K is still fast but less memory consuming in case of a busy site.
-
IAdapter over 13 yearsWhat about using channels and Channel.transferTo ?
-
user207421 over 13 years@01: Yes, you can use NIO's channels if you use Channels.newChannel(OutputStream). Which wraps the output stream in a channel. It is still talking to an underlying ByteArrayOutputStream. There is no efficiency gain in this situation. It is pointless.
-
Adam Rabung over 12 years+1 ymmv, but i've had a hard time making the nio version faster than good old streams
-
brady about 11 years@IAdapter In general, using
transferTo()
will give the best performance; unfortunately, the Servlet API doesn't expose theSocketChannel
, so the optimization isn't available. -
user207421 over 7 years@JerylCook I addessed that in comments five and a half years ago and have so far attracted 5 comment votes for having done so. Look.