在Java中将二进制下载文件写入磁盘

8
我有一个软件,可以在JavaScript文件(.js)中编写插件,从而使用Java函数(我不知道这是否常见,我以前从未在JavaScript文件中看到过Java调用)。
我需要从Web服务器下载二进制文件并将其写入硬盘。我尝试了以下代码:
baseencoder = new org.apache.commons.codec.binary.Base64();
url = new java.net.URL("https://server/file.tgz");

urlConnect = url.openConnection();
urlConnect.setDoInput(true);
urlConnect.setDoOutput(true);
urlConnect.setRequestProperty("authorization","Basic "+ java.lang.String(baseencoder.encodeBase64(java.lang.String( username + ":" + password ).getBytes())));
urlConnect.setRequestProperty("content-type","application/x-www-form-urlencoded");

is = new java.io.DataInputStream(urlConnect.getInputStream());
fstream = new FileWriter("C:\\tmp\\test.tgz");
out = new BufferedWriter(fstream);
while((data = is.read()) != -1){
    out.write(data);
}

out.close();
is.close();

生成的文件不再是一个有效的gzip档案。如果我犯了什么错误,很抱歉,但我不是程序员,也不太了解Java。

5个回答

34

不要使用FileWriter - 它试图将数据转换为文本。

只需使用FileOutputStream

byte[] buffer = new byte[8 * 1024];

InputStream input = urlConnect.getInputStream();
try {
  OutputStream output = new FileOutputStream(filename);
  try {
    int bytesRead;
    while ((bytesRead = input.read(buffer)) != -1) {
      output.write(buffer, 0, bytesRead);
    }
  } finally {
    output.close();
  }
} finally {
  input.close();
}

1
另外,在 while 循环中,你需要使用正确的测试条件:while((data = is.read()) != null){ ... }。 - Matt Ball
感谢使用FileOutputStream(我仍然只使用简单的read()因为似乎不可能在JavaScript中使用字节缓冲区,因为它不是一个对象。 - radius

9

我知道这个问题已经有了答案,但更简单的方法是使用Apache Commons IO的IOUtils.copy()方法,它可以完全复制一个InputStream到一个OutputStream中。


2

DataInputStream 用于读取 Java 原始类型数据,而不是通用数据。

它也是多余的,因为 urlConnect.getInputStream(); 已经返回了一个 InputStream,而所有的 InputStream 都支持 read() 方法。

is = urlConnect.getInputStream();

注意:这里假设isbis是同一个变量,否则你在循环中读取了错误的流。


不错的信息!有趣的是,尽管名称表明DataInputStream不适用于通用数据..! - Gewure

0

刚刚了解了LimitInputStream,听起来它可以完全满足你的需求,通过缓冲输入流来提高效率。


0

你甚至可以使用NIO FileChannel#transferFrom方法。

            URL website = new URL(urlToDownload);

            try (ReadableByteChannel rbc = Channels.newChannel(website.openStream());
                    FileOutputStream fos = new FileOutputStream(filePath);) {
                fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
            }

参考 链接1, 链接2


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接