用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

然而,我可以用"方舟"打开它,并正确提取其中的内容。

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

我是不是错过了什么?

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

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

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

想象一下,这个文件是16385字节。

第一个CCD_ 1将填满整个缓冲器并返回16384。然后,您将写入整个缓冲区。第二次,它将读取一个字节,然后再写入整个缓冲区。

有人打败了我,但我想补充一点,你可以用IOUtils来做这件事。。。

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

例如IOUtils.copy(in, out)

最新更新