Java - 使用缓冲区通过网络下载文件

3
我希望您能直接从网络流中读取并将字节写入文件。但每次运行程序时,实际上只写入了很少的字节。
Java:
InputStream in = uc.getInputStream();
int clength=uc.getContentLength();
byte[] barr = new byte[clength];
int offset=0;
int totalwritten=0;
int i;
int wrote=0;

OutputStream out = new FileOutputStream("file.xlsx");
while(in.available()!=0) { 
   wrote=in.read(barr, offset, clength-offset);
   out.write(barr, offset, wrote);
   offset+=wrote;
   totalwritten+=wrote;
}
System.out.println("Written: "+totalwritten+" of "+clength);
out.flush();
2个回答

4
那是因为available()并不是你想象中的那样。请阅读其API文档。你应该简单地读取,直到由read()返回的字节数为-1。或者更简单的方法,使用Files.copy()
Files.copy(in, new File("file.xlsx").toPath());

如果使用与输入流大小相同的缓冲区,基本上就失去了使用缓冲区的目的,即只在内存中保存少量字节。

如果想重新实现copy(),通常的模式如下:

byte[] buffer = new byte[4096]; // number of bytes in memory
int numberOfBytesRead;
while ((numberOfBytesRead = in.read(buffer)) >= 0) {
    out.write(buffer, 0, numberOfBytesRead);
}

代码段的第四行不应该是偏移变量而不是0吗? - Giorgos Fandomas
1
请阅读 API 文档(再次阅读):第一个读取的字节存储在元素 b[0] 中,下一个字节存储在 b[1] 中,以此类推。读取的字节数最多等于 b 的长度。 - JB Nizet
非常正确。谢谢。因此,第4行中的零是用于表格中的偏移量而不是文件中的偏移量。 - Giorgos Fandomas

0

你在错误地使用.available()方法。根据Java文档

available()方法返回一个估计值,表示在下一次调用该输入流的方法之前,可以从该输入流中读取(或跳过)的字节数。

这意味着,当你的流速度第一次慢于文件写入速度时(很快就会发生),while循环就会结束。

你可以准备一个线程,在等待期间读取所有预期内容的长度(当然要设置合理的超时时间),或者如果用户交互不是太重要的话,就将程序阻塞在等待状态。


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