繁体   English   中英

使用Java读写大型二进制文件

[英]Read and Write large binary files with Java

因此,我有这段代码可以从磁盘(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”打开它并正确提取其内容。

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

我想念什么吗?

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

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

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

假设文件为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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM