优化Java中读取大型InputStream的性能

6
我想读取一个大的InputStream并将其作为字符串返回。 这个InputStream很大。所以,通常在执行时需要花费很多时间和大量的内存。 以下代码是我目前开发的代码。 我需要将这段代码转换为在更少的时间和更少的内存消耗下完成任务的代码。
你能给我任何想法吗?
BufferedReader br =
    new BufferedReader(
        new InputStreamReader(
            connection.getInputStream(),
            "UTF-8")
        );

StringBuilder response = new StringBuilder(1000);

char[] buffer = new char[4096];

int n = 0;
while(n >= 0){
    n = br.read(buffer, 0, buffer.length);
    if(n > 0){
        response.append(buffer, 0, n);
    }
}
return response.toString();

谢谢!


2
“lot” of memory是什么意思?你不可避免地需要足够的内存来容纳你正在构建的整个字符串。你是否看到了比你预期更严重的情况? - djna
是的,消耗的内存与响应(字符串)的大小成正比,这是事实。但在这里,重点是有效地使用内存(减少不必要的内存使用等)。例如,在这里我使用了StringBuilder而不是使用+'s将输入附加到相同的字符串中(如str = str + newStr),以减少不必要的内存使用。像这样,我期望有更多的想法来通过管理内存和加速代码使我的代码更好。 - Namalak
我正在读取一个二进制数据数组,该数组是作为响应传递给使用URL传递的一组参数所创建的连接。代码如下:URL url = new URL(sendURL); HttpURLConnection connection = (HttpURLConnection)url.openConnection(); - Namalak
2
我想读取一个大的InputStream并将其作为String返回。但实际上你可能根本不想这样做。如果String很大,你会冒着内存不足的风险,而如果它相对较小,你仍然会增加延迟。你应该考虑重新组织调用此方法的代码,以便它可以使用Reader或InputStream。 - user207421
“你应该考虑重新组织调用此方法的程序”,这句话是什么意思?“重新组织”是什么意思?我不明白。 - Namalak
显示剩余2条评论
5个回答

3

当你在进行缓冲I/O时,你可以从缓冲读取器中一次只读取一个字符。然后逐步构建字符串,并在结尾处使用toString()。


这不是读取字符,将它们存储到字符数组中比读取每个字符并构建字符串更好吗?我的意思是read()与read(char[], int start, int end)。 - Namalak
1
这就是缓冲读取器在底层执行的操作...尝试查看BufferedReader的源代码。 - Thorbjørn Ravn Andersen

1
你可能会发现,在某些操作系统上,对于较大的文件,通过 FileChannel.map映射文件将提供更好的性能-映射文件,然后从映射的ByteBuffer创建字符串。不过你需要进行基准测试,因为在某些情况下,“传统”的IO可能更快。

是的,我对FileChannel.map还不熟悉。这能与读取URL的OP一起使用吗? - Namalak
@dogbane和Namalak:公平地说,在我回答之后,这一点并没有被明确指出 :) 我会把它留在这里,以防后来有人想为一个文件做同样的事情。 - Steven Schlansker

0

你是否事先知道字符串的最大长度?你目前为缓冲区指定了1000的初始容量。如果读取的内容比这个要大得多,你将支付一些分配更大内部缓冲区的成本。

如果你控制正在读取的对象的生命周期,也许你可以分配一个可重复使用的字节数组作为缓冲区。从而避免垃圾回收。


0
增加缓冲区的大小。缓冲区越大,读取所有数据的速度就越快。如果您知道(或可以计算出)流中可用的字节数,甚至可以预先分配相同大小的缓冲区。

谢谢。目前1000已经很好了。不必要地增加缓冲区大小也是低效的,不是吗? - Namalak
我指的是你设置为4096的字符缓冲区。 - dogbane

0

你可以在一个单独的线程中运行代码...虽然不会更快,但至少你的程序能够在等待流数据时做一些其他工作。


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