【问题标题】:Read and Write large binary files with Java使用 Java 读写大型二进制文件
【发布时间】:2016-09-20 10:16:01
【问题描述】:

所以我有这段代码,它从磁盘(tar.gz、exe 或 dmg)读取正确的安装程序文件,并将其流式传输给用户(代码如下)。安装程序其实是压缩包,可以解压,手动运行安装(Windows专用,Mac安装程序需要挂载,Unix安装程序也需要解压)

    InputStream in = null;
    OutputStream out = null;

    byte[] buffer = new byte[16384];

    try {
        String bundle = ServletRequestUtils.getRequiredStringParameter(request, "bundle");

        String installerPath = constructFilePath(bundle);
        File installer = new File(installerPath);
        if(!installer.exists()){
            logger.error("Cannot read installer file");
            response.sendRedirect("/somewhere");
        }else{
            in = new FileInputStream(installer);
            response.setContentType(getBundleContentType(bundle)); //application/octet-stream or application/x-gzip or application/x-apple-diskimage
            response.setHeader("Pragma", "private"); 
            response.setHeader("Cache-Control", "private, must-revalidate"); 
            response.addHeader("Content-Disposition", "attachment;filename="+getBundleFileName(bundle)); //Setting new file name
            out = new BufferedOutputStream(response.getOutputStream());

            while((in.read(buffer)) != -1)
                out.write(buffer);
        }
    } catch (Exception e) {
        logger.error("Exception downloading installer file, reason: " + e);
        response.sendRedirect("/somewhere");
    } finally {
        if(in != null){
            in.close();
        }
        if(out != null){
            out.flush();
            out.close();
        }
    }

    return null;

我将以 Windows (.exe) 安装程序为例。以前,当我将代码重定向到 http:///somepath/installer.exe 进行下载时,该文件已经下载,我可以用 7zip 解压它,但现在,当我尝试解压它时使用 7zip,我得到了:

Cannot open file as archive.

但是,我可以双击 .exe 并成功进行安装。我也可以使用 winRAR 提取它。

Unix 安装程序也发生了同样的事情。当我将它下载到 Unix 机器并尝试提取它(通过右键单击“在此处提取”)时,我收到此错误:

gzip: stdin: decompression OK, trailing garbage ignored 
/bin/gtar: Child returned status 2 
/bin/gtar: Error is not recoverable: exiting now

但是,我可以用“ark”打开它并正确提取其内容。

我还应该指出,下载后文件的字节不匹配(下载的字节与文件系统上的字节相比,应该是相同的)。

我错过了什么吗?

【问题讨论】:

    标签: java file stream binary


    【解决方案1】:

    您可以尝试写入与您读取的完全相同的数据:

    while ((read = in.read(buffer)) != -1) {
        out.write(buffer, 0, read);
    }
    

    【讨论】:

      【解决方案2】:

      这是因为您正在写入整个缓冲区。

      假设文件是​​ 16385 字节。

      第一个in.read(buffer) 将填满整个缓冲区并返回 16384。然后您将写入整个缓冲区。第二次,它会读取一个字节,然后再写入整个缓冲区。

      有人打败了我,但我要补充一点,您可以使用 IOUtils 来执行此操作...

      http://commons.apache.org/proper/commons-io/javadocs/api-release/org/apache/commons/io/IOUtils.html

      例如IOUtils.copy(in, out)

      【讨论】:

        猜你喜欢
        • 2014-12-19
        • 1970-01-01
        • 2014-04-27
        • 2015-11-29
        • 1970-01-01
        • 1970-01-01
        • 2012-01-26
        • 2018-07-26
        • 2016-06-14
        相关资源
        最近更新 更多