2012-02-11 134 views
0

我正在从网络上下载数据库,大小介于100千字节和500千字节之间。这里是我的代码(删除无用代码):FileOutputStream真的很慢

URLConnection uConnection = downloadUrl.openConnection(); 
InputStream iS = uConnection.getInputStream(); 
BufferedInputStream bIS = new BufferedInputStream(iS); 
byte[] buffer = new byte[1024]; 
FileOutputStream fOS = new FileOutputStream(db); 
int bufferLength = 0; 
while ((bufferLength = bIS.read(buffer)) > 0) { 
fOS.write(buffer, 0, bufferLength); 
} 
fOS.close(); 

我的问题是,他需要很长时间才能完成while语句。我把代码搞乱了吗?对于这样的小文件不应该花那么长时间,不是吗?我在谈论1分钟,三个文件不超过1 MB ...预先感谢!

+2

什么让你觉得这个问题是'FileOutputStream'?这个问题可能很容易被带宽下载资料。你用过类似Traceview来确定你正在花费的地方 你的时间? – CommonsWare 2012-02-11 16:40:55

+0

我不知道Traceview是什么。我调试了代码,这是因为while语句它非常慢。我也认为,当我的InputStream-Object被实例化时,数据的下载就完成了。还是不是在那里下载的? – ezcoding 2012-02-11 16:44:53

+0

使用缓冲区大小1024是恕我直言,一个坏主意。在智能手机中,所有媒体通常具有4096字节或更大的块大小(例如SD卡)。 – Robert 2012-02-11 16:49:58

回答

4

“慢”真的很模糊。这就是说,考虑你想要做什么,你不应该使用BufferedInputStream,你的buffer太小了。

的缓冲包装是用于优化小的读/写。由于您所做的只是尽可能快地读取大量数据,因此您应该直接从InputStream中读取数据,并使用大缓冲区(例如,64k,因为底层本机代码可能会在该处大块大小)。

byte[] buffer = new byte[65536]; 
... 
while ((bufferLength = iS.read(buffer, 0, buffer.length) > 0) { 
    ... 
+0

我会尝试。有关于Java I/O的良好在线文献吗?它有点让我很困惑:) – ezcoding 2012-02-11 16:59:01

+1

我不得不谷歌周围,但这不是特定于Java。想想这样 - 如果你必须把一堆水从一个地方移到另一个地方,那会更快;使用16盎司杯子还是5gal桶子?有了这个小缓冲区,你不得不填充和清空它很多次,这是有成本的。当你知道你将需要一堆水时,缓冲包装纸是用来做的,但一次只想处理一杯水。它预取桶并让你从中取出杯满。当水桶是空的时候,它会补充它。 – 2012-02-11 17:07:27

+0

好吧,谢谢:) – ezcoding 2012-02-11 17:17:11

-3

我发现在jdk的1.7真正的解决方案,这是由可靠,快速,简单的制作和几乎明确将产生于可惜面纱旧的java.io solutions.Despite网络仍然是充足充分利用在输入/输出流,我会warmely建议大家使用一个简单的方法在Java中复制文件的例子:java.nio.Files.copy(路径起点,路径目的地)可选参数更换目的地,迁移元数据文件属性,甚至尝试文件的事务性移动(如果基础OS允许的话)。这是一份非常好的工作,等待了这么久!您可以轻松地从副本(file1文件,文件文件2)通过附加一个“.toPath()”的文件实例转换代码(例如file1.toPath(),file2.toPath()进行说明,布尔方法isSameFile(file1.toPath(),file2.toPath()),已经使用上述复制方法里面,但你想要任何情况下轻松使用。对于每一个情况下,你不能使用社区图书馆升级到1.7从阿帕奇(公共-IO)或谷歌(番石榴公地)仍建议。

+2

这与从套接字读取数据并写入它有什么关系一份文件? – 2012-02-17 15:13:10