When I want to write the full contents of a file into an OutputStream
, I usually allocate a buffer as a byte[]
, then make a for
loop to read
data from the file's InputStream
into the buffer and write the buffer contents into the OutputStream
, until the InputStream
has no more bytes available.
This seems rather clumsy to me. Is there a better way to do this?
Also, I am always unsure about the buffer size. Usually, I am allocating 1024 bytes, because it just feels good. Is there a better way to determine a reasonable buffer size?
In my current case, I want to copy the full contents of a file into the output stream that writes the contents of an HTTP response. So, this is not a question about how to copy files on the file system.
For Java 1.7+ you can use the Files.copy(Path, OutputStream), e.g.
HttpServletResponse response = // ...
File toBeCopied = // ...
try (OutputStream out = response.getOutputStream()) {
Path path = toBeCopied.toPath();
Files.copy(path, out);
out.flush();
} catch (IOException e) {
// handle exception
}
Note, since you are dealing with HttpServletResponse
is is also a good idea to set correct response headers. Add the following lines before you copy the actual file data to the response:
String mimeType = URLConnection.guessContentTypeFromName(toBeCopied.getName());
String contentDisposition = String.format("attachment; filename=%s", toBeCopied.getName());
int fileSize = Long.valueOf(toBeCopied.length()).intValue();
response.setContentType(mimeType);
response.setHeader("Content-Disposition", contentDisposition);
response.setContentLength(fileSize);
Note, the encoding of the file name passed to the content disposition is important, see this question.
Apache Commons-IO:
IOUtils.copy(fileInputStream,outputStream);
JDK NIO
new FileInputStream(file).getChannel().transferTo(otherChannel);
With commons-io you have a one-line solution:
IOUtils.copy(yourFileInputStream, outputStream);
Note that you'd have to close your streams manually (or by IOUtils.closeQuitely(..)
)