Есть ли лучший способ написать полное содержимое файла в OutputStream?
Когда я хочу написать полное содержимое файла в OutputStream
, я обычно выделяю буфер как byte[]
, а затем создаю цикл for
для read
данных из файла InputStream
в буфера и записать содержимое буфера в OutputStream
, пока InputStream
не будет иметь больше байтов.
Это кажется довольно неуклюжим для меня. Есть ли лучший способ сделать это?
Кроме того, я всегда не уверен в размере буфера. Обычно я выделяю 1024 байта, потому что он просто чувствует себя хорошо. Есть ли лучший способ определить разумный размер буфера?
В моем текущем случае я хочу скопировать полное содержимое файла в выходной поток, который записывает содержимое ответа HTTP. Итак, это не вопрос о том, как копировать файлы в файловой системе.
Ответы
Ответ 1
Для Java 1.7+ вы можете использовать Files.copy(Path, OutputStream), например
HttpServletResponse response = // ...
File toBeCopied = // ...
try (OutputStream out = response.getOutputStream()) {
Path path = toBeCopied.toPath();
Files.copy(path, out);
out.flush();
} catch (IOException e) {
// handle exception
}
Примечание. Поскольку вы имеете дело с HttpServletResponse
, также рекомендуется установить правильные заголовки ответов. Добавьте следующие строки, прежде чем копировать фактические данные файла в ответ:
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);
Обратите внимание: важна кодировка имени файла, переданного в распоряжение содержимого, см. этот вопрос.
Ответ 2
Apache Commons-IO:
IOUtils.copy(fileInputStream,outputStream);
JDK NIO
new FileInputStream(file).getChannel().transferTo(otherChannel);
Ответ 3
С commons-io у вас есть однострочное решение:
IOUtils.copy(yourFileInputStream, outputStream);
Обратите внимание, что вам придется закрыть свои потоки вручную (или IOUtils.closeQuitely(..)
)