Есть ли лучший способ записать полное содержимое файла в OutputStream? - PullRequest
17 голосов
/ 20 января 2011

Когда я хочу записать полное содержимое файла в OutputStream, я обычно выделяю буфер как byte[], затем делаю цикл for для read данных из файла InputStream в файл буфер и запишите содержимое буфера в OutputStream, пока у InputStream не будет больше доступных байтов.

Мне это кажется довольно неуклюжим. Есть ли лучший способ сделать это?

Кроме того, я всегда не уверен в размере буфера. Обычно я выделяю 1024 байта, потому что это просто хорошо. Есть ли лучший способ определить разумный размер буфера?

В моем текущем случае я хочу скопировать полное содержимое файла в выходной поток, который записывает содержимое HTTP-ответа. Таким образом, это не вопрос о том, как копировать файлы в файловой системе.

Ответы [ 3 ]

24 голосов
/ 21 октября 2014

Для 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);

Обратите внимание, что важна кодировка имени файла, передаваемого в расположение содержимого, см. этот вопрос .

22 голосов
/ 20 января 2011

Apache Commons-IO:

IOUtils.copy(fileInputStream,outputStream);

JDK NIO

new FileInputStream(file).getChannel().transferTo(otherChannel);
9 голосов
/ 20 января 2011

С commons-io у вас есть однострочное решение:

IOUtils.copy(yourFileInputStream, outputStream);

Обратите внимание, что вам придется закрыть свои потоки вручную (или IOUtils.closeQuitely(..))

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...