使用BufferedReader.readLine()读取inputStream太慢了

Loh*_*hit 39 java sockets io

我正在使用以下代码.

BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = null;

StringBuilder responseData = new StringBuilder();
while((line = in.readLine()) != null) {
    responseData.append(line);
}
Run Code Online (Sandbox Code Playgroud)

但阅读200行需要12秒以上.

请帮忙

Jon*_*eet 30

我强烈怀疑这是因为网络连接或你正在谈论的网络服务器 - 这不是BufferedReader错.试着测量一下:

InputStream stream = conn.getInputStream();
byte[] buffer = new byte[1000];
// Start timing
while (stream.read(buffer) > 0)
{
}
// End timing
Run Code Online (Sandbox Code Playgroud)

我想你会发现它几乎与解析文本的时间完全相同.

请注意,您还应该提供InputStreamReader适当的编码 - 平台默认编码几乎肯定不是您应该使用的.

  • @Shashi:是的,因为那是它实际从网络上读取的地方.除非这些行很大,否则这实际上不会是BufferedReader/InputStreamReader开销. (6认同)

Pet*_*rey 8

我有一个更长的测试尝试.这需要平均160 ns来读取每一行,因为它将它添加到List(这可能是你想要的,因为删除换行不是很有用.

public static void main(String... args) throws IOException {
    final int runs = 5 * 1000 * 1000;

    final ServerSocket ss = new ServerSocket(0);
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                Socket serverConn = ss.accept();
                String line = "Hello World!\n";
                BufferedWriter br = new BufferedWriter(new OutputStreamWriter(serverConn.getOutputStream()));
                for (int count = 0; count < runs; count++)
                    br.write(line);
                serverConn.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }).start();

    Socket conn = new Socket("localhost", ss.getLocalPort());

    long start = System.nanoTime();
    BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
    String line;

    List<String> responseData = new ArrayList<String>();
    while ((line = in.readLine()) != null) {
        responseData.add(line);
    }
    long time = System.nanoTime() - start;
    System.out.println("Average time to read a line was " + time / runs + " ns.");
    conn.close();
    ss.close();
}
Run Code Online (Sandbox Code Playgroud)

版画

Average time to read a line was 158 ns.
Run Code Online (Sandbox Code Playgroud)

如果你想构建一个StringBuilder,保留换行符,我会建议采用以下方法.

Reader r = new InputStreamReader(conn.getInputStream());
String line;

StringBuilder sb = new StringBuilder();
char[] chars = new char[4*1024];
int len;
while((len = r.read(chars))>=0) {
    sb.append(chars, 0, len);
}
Run Code Online (Sandbox Code Playgroud)

还是打印

Average time to read a line was 159 ns.
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,速度都受发送者而不是接收者的限制.通过优化发送器,我将此时间降低到每行105 ns.