输入流读取大文件非常慢,为什么?

时间:2014-04-29 21:06:54

标签: java file-upload file-io inputstream large-files

我正在尝试提交500 MB的文件。 我可以加载它,但我想提高性能。 这是慢代码:

File dest = getDestinationFile(source, destination);
if(dest == null) return false;

in = new BufferedInputStream(new  FileInputStream(source));
out = new BufferedOutputStream(new  FileOutputStream(dest));
byte[] buffer = new byte[1024 * 20];
int i = 0;

// this while loop is very slow
while((i = in.read(buffer)) != -1){
   out.write(buffer, 0, i); //<-- SLOW HERE
   out.flush();
}

我怎样才能找到缓慢的原因? 字节数组大小/缓冲区大小不够吗? 您有什么想法来改善表现吗?

提前感谢您提供任何帮助

1 个答案:

答案 0 :(得分:3)

你不应该在循环中刷新。 您正在使用BufferedOutputStream。这意味着在“缓存”一些数据后,它会将数据刷新到文件。 您的代码只是在写入少量数据后通过刷新数据来杀死性能。

尝试这样做:

while((i = in.read(buffer)) != -1){
out.write(buffer, 0, i); <-- SLOW HERE
}
out.flush();

.. ::编辑:回应以下评论:: ..
在我看来,你根本不应该使用缓冲区。您正在使用缓冲(输出/输入)流,这意味着他们有自己的缓冲区来从磁盘读取数据的“包”并保存数据的“包”。我不是100%肯定使用额外缓冲区的性能,但我希望你展示我将如何做到这一点:

File dest = getDestinationFile(source, destination);
if(dest == null) return false;

in = new BufferedInputStream(new  FileInputStream(source));
out = new BufferedOutputStream(new  FileOutputStream(dest));

int i;
while((i = in.read()) != -1){
   out.write(i);
}
out.flush();

在我的版本中,您只需读取一个字母(不是一个整数。阅读文档:
http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html#read()
这个方法返回int,但这只是一个BYTE)但是没有必要读取整个缓冲区(因此你不必担心它的大小)。

可能你应该阅读更多关于溪流的内容,以便更好地理解与它们有关的内容。