【问题标题】:Is there a better way to write the full contents of a file to an OutputStream?有没有更好的方法将文件的全部内容写入 OutputStream?
【发布时间】:2011-06-12 02:27:25
【问题描述】:

当我想将文件的全部内容写入OutputStream时,我通常会分配一个缓冲区作为byte[],然后将for循环到read文件的InputStream中的数据缓冲区并将缓冲区内容写入OutputStream,直到InputStream 没有更多可用字节。

这对我来说似乎很笨拙。有没有更好的方法来做到这一点?

另外,我总是不确定缓冲区的大小。通常,我分配 1024 个字节,因为感觉很好。有没有更好的方法来确定合理的缓冲区大小?

在我目前的情况下,我想将文件的全部内容复制到写入 HTTP 响应内容的输出流中。所以,这不是关于如何在文件系统上复制文件的问题。

【问题讨论】:

    标签: java io


    【解决方案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);
    

    注意,传递给内容处置的文件名的编码很重要,请参阅this question

    【讨论】:

    • 我的单元测试如何验证正在写入 OutputStream 的内容? ServletOutputStream mockOutput = mock(ServletOutputStream.class); when(response.getOutputStream()).thenReturn(mockOutput);
    【解决方案2】:

    Apache Commons-IO:

    IOUtils.copy(fileInputStream,outputStream);
    

    JDK NIO

    new FileInputStream(file).getChannel().transferTo(otherChannel);
    

    【讨论】:

    • 哇。我在 Bozho 的回答中对 Commons-IO 做了一个简短的评论。但渠道解决方案正是我想要的。非常感谢,所有的 NIO 通道都让我擦肩而过,因为在 NIO 出现之前我已经学习了 Java IO。而且,顺便说一句:9分钟!这几乎和闪电一样快。
    • 别忘了关闭FileInputStream
    【解决方案3】:

    使用commons-io,您有一个单一的解决方案:

    IOUtils.copy(yourFileInputStream, outputStream);
    

    请注意,您必须手动(或通过IOUtils.closeQuitely(..))关闭您的流

    【讨论】:

    • 这也是我的建议。虽然它的作用是一样的。
    • 看起来真不错。但是对于这个简单的任务,包含另一个库对我来说似乎有点过头了。当然,如果有更多理由包含 Commons-IO,那么这将是首选的解决方案。
    猜你喜欢
    • 2012-06-30
    • 2020-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-29
    相关资源
    最近更新 更多