Most effective way to write File to ServletOutputStream

50,985

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();
}
Share:
50,985
IAdapter
Author by

IAdapter

Updated on August 12, 2020

Comments

  • IAdapter
    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
    Bozho over 13 years
    +1, but two notes - it's "apache commons", and you can use IOUtils.closeQuitely(..)
  • Sean Patrick Floyd
    Sean Patrick Floyd over 13 years
    @Bozho it used to be called Jakarta Commons many years ago :-)
  • IAdapter
    IAdapter over 13 years
    that doesn't work for me, I don't want to add Commons IO jar just for that functionality.
  • IAdapter
    IAdapter over 13 years
    won't this be more effective if the NIO was used?
  • IAdapter
    IAdapter over 13 years
    won't this be more effective if the NIO was used?
  • Mihai Toader
    Mihai Toader over 13 years
    i 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
    Bozho over 13 years
    @01 adding a dependency on apache commons rarely has any downsides ;)
  • IAdapter
    IAdapter over 13 years
    Bozho 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
    AngerClown over 13 years
    The 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
    BalusC over 13 years
    Difference 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
    IAdapter over 13 years
    What about using channels and Channel.transferTo ?
  • user207421
    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
    Adam Rabung over 12 years
    +1 ymmv, but i've had a hard time making the nio version faster than good old streams
  • brady
    brady about 11 years
    @IAdapter In general, using transferTo() will give the best performance; unfortunately, the Servlet API doesn't expose the SocketChannel, so the optimization isn't available.
  • user207421
    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.