【问题标题】:What's the fastest way to read from InputStream?从 InputStream 中读取的最快方法是什么?
【发布时间】:2015-01-20 16:47:35
【问题描述】:

我正在尝试从 HttpURLConnection 的输入流中读取数据:

InputStream input = conn.getInputStream();
InputStreamReader isr = new InputStreamReader((input));
BufferedReader br = new BufferedReader(isr);

StringBuilder out = new StringBuilder("");
String output;
while ((output = br.readLine()) != null) {
    out.append(output);
}

当输入流包含大量数据时,这确实会花费太多时间。可以优化吗?

【问题讨论】:

  • 是什么让您认为瓶颈在您​​的代码中,而不是数据通过网络到达所花费的时间?
  • 您可以为BufferedReader 使用更大/更小的缓冲区大小进行测试。否则您会受到网络的限制。
  • “太多”实际上是否比使用其他方式(ftp、浏览器、wget 等)下载资源时更多?衡量,不要猜测。你期望多少 KB/s,你得到多少?请注意,构建巨大的 StringBuilders 可能需要很多时间。如果全部在内存中,就会有大量的数组复制和内存分配。
  • @laune:我觉得应该不会比网络慢...
  • @biziclop 我实际上已经看到了双重/复制来减慢速度。检查是一回事 - 因此评论不是答案;-)

标签: java performance inputstream


【解决方案1】:

也许这会更快一些,因为 Java 8 中的新 Stream API 使用内部并行机制:

package testing;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.stream.Stream;

public class StreamTest {

  /**
   * @param args the command line arguments
   * @throws java.io.IOException
   */
  public static void main(String[] args) throws IOException {
    URL url = new URL("http://www.google.com");
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setUseCaches(false);
    if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
      BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));

      Stream<String> s = br.lines();
      s.parallel().forEach(System.out::println);      
    }
  }

}

【讨论】:

  • 那么你可能已经完成了 fastet 的实现。也许并发读取将是另一种选择:stackoverflow.com/questions/16159183/…,如果您决定切换到 Java 8,这将很有帮助:stackoverflow.com/questions/1605332/…
  • 感谢您的提示。在我的代码中,bufferedReader.readLine() 是执行时间最多的代码
  • 事实上并没有更快。 20kb 的字符串仍然需要 10s 左右
【解决方案2】:

这段代码没有什么慢的。如果输入到达的速度足够快,您可以每秒读取数百万行。您的时间可能根本没有花在读取输入流上,而是用于阻塞等待输入或附加到StringBuilder

但你根本不应该这样做。大多数文件可以一次处理一行或一次处理一条记录。编译器一次处理一个令牌,没有比编译更复杂的文件处理任务了。有可能。

【讨论】:

  • 如果你说“时间......花费......附加到 StringBuilder”:你不是在反驳你的说法“这段代码没有什么慢的。”?
  • 我做了一些措施:等待输入需要 12-13 秒,读取流 + 构建 StringBuilder 需要 40-55 秒。
【解决方案3】:

在 java 输入流中我们有方法 read(byte b[],off,len) 它将输入流中的 读取到给定的字节数组中。 这里 off 是数组的起始索引,len 是要读取的最大字节数,b[] 是字节数组。 Read 方法将尝试读取最大 len 个字节,但此方法返回实际读取的字节数,因为我将无法读取所需的字节数。 这是示例:-

FileInputStream i=new FileInputStream("file path");
FIleOutputStream o=new FileOutputStream("file path");
byte a[]=new byte[1024];
for(int j;(j=i.read(a,0,1024))!=-1;){
    o.write(a,0,j);
}                             

【讨论】:

    猜你喜欢
    • 2011-10-26
    • 1970-01-01
    • 2011-08-11
    • 1970-01-01
    • 2019-09-13
    • 2016-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多