Java中高效的将输入流转换为字符串的方法

4

我在Java应用程序中运行了一款分析器(即性能分析工具),惊讶地发现除了需要进行HTTP请求的方法外,耗时最长的竟然是我的 inputStreamToString 方法。该方法目前的定义如下:

public static String inputStreamToString(InputStream in) throws IOException {
    BufferedReader reader = new BufferedReader(new InputStreamReader(in));
    StringBuilder sb = new StringBuilder();
    String line = null;
    while ((line = reader.readLine()) != null) {
        sb.append(line).append("\n");
    }
    in.close();
    return sb.toString();
}

如何使这更快?(是的,我确实需要字符串,不,输入字符串并不那么大,不,这种方法被调用的频率比程序中大多数方法要少,不,没有办法避免需要进行转换。)


1
那就是所有的I/O操作发生的地方(我假设分析器包括readLine()等待数据到来所需的所有时间)。唯一明显的事情是,您可以使用足够大的缓冲区预初始化StringBuilder,以便它不必重新分配内存,但我想一切都被读取数据所需的时间所淹没了。 - EboMike
@EboMike 已经几乎解决了这个问题。除此之外,我能想到的唯一一件事就是跳过 BufferedReader 并提供自己的缓冲区来读入——这也可以节省 readLine 调用,因为你真的不在意一次只读取一行。 - casablanca
我想我最好把它变成一个答案 :) - EboMike
除非你想转换行尾或解析行,否则逐行阅读没有太多意义。我宁愿通过固定大小的缓冲区逐个字符地读取:gist.github.com/fkirc/a231c817d582e114e791b77bb33e30e9 - Mike76
2个回答

5
好的,这就是所有的I/O操作发生的地方(我假设分析器包括等待数据传入所需的所有readLine()时间)。唯一明显的事情是,您可以使用足够大的缓冲区预初始化StringBuilder,以便它不必重新分配内存,但我认为读取数据所需的时间使得这一切都微不足道。
除此之外 - 您受到I/O限制。通过网络接收数据需要时间。
编辑:还可以包括casablanca的评论:不要逐行读取然后添加换行符,您可以使用具有合理大缓冲区的简单读取器,并且只阻止读取所有内容。既然您似乎只是复制整个输入数据,因此没有必要逐行读取。手动逐行进行的唯一理由是如果您想将新行(如\r\n)标准化为一个标准的\n

0

尝试使用来自Jakarta Commons的IOUtils.copy()。创建ByteArrayOutputStream,将字节从HTTPRequest流复制到此ByteArray,然后使用new String(bytes,"UTF-8")创建字符串。

我相信它可以更快...

但是您的代码看起来像是为了说明良好的风格和良好的编码而编写的。我真的不明白这里可能有多么低效。可能需要时间,因为您的其余逻辑相对简单且编写得很好?我的意思是,尽管这段代码需要相对较长的时间,但这并不太关键?


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