使用 BufferedReader.readLine() 读取 inputStream 太慢
Posted
技术标签:
【中文标题】使用 BufferedReader.readLine() 读取 inputStream 太慢【英文标题】:Reading inputStream using BufferedReader.readLine() is too slow 【发布时间】:2011-08-01 11:18:25 【问题描述】:我正在使用以下代码。
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = null;
StringBuilder responseData = new StringBuilder();
while((line = in.readLine()) != null)
responseData.append(line);
但读取 200 行需要超过 12 秒。
请帮忙
【问题讨论】:
你有没有想到客户端也可能是慢的?还是网络? 什么是conn
?如果您直接阅读 InputStream
会更快(进入您将丢弃的 byte[]
吗?
从读取什么?如果问题与缓冲有关,我会感到惊讶。你是通过网络阅读吗?例如,您是否从最后一行没有行终止符的网络连接获取数据,以便 readLine
坐在那里等待它可以识别为行尾的东西?还是来自真正缓慢发送数据的东西?
问题出在while循环中。我测量了时间
你不认为读取过程不能比写入过程快的想法值得考虑吗?您测量了时间 - 当然,但您似乎无法解释您的测量结果。就像我测量了一辆红色汽车的速度,然后坚持认为是红色让它跑得那么快。
【参考方案1】:
我有一个更长的测试要尝试。读取每一行并将其添加到列表中平均需要 160 ns(这可能是您想要的,因为删除换行符不是很有用。
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();
打印
Average time to read a line was 158 ns.
如果您想构建一个 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);
仍然打印
Average time to read a line was 159 ns.
在这两种情况下,速度都受到发送者而非接收者的限制。通过优化发送器,我将这个时间降低到每行 105 ns。
【讨论】:
使用第二种方法实际上对我来说快一点,谢谢【参考方案2】:我强烈怀疑这是因为网络连接或您正在与之交谈的网络服务器 - 这不是 BufferedReader
的错。尝试测量这个:
InputStream stream = conn.getInputStream();
byte[] buffer = new byte[1000];
// Start timing
while (stream.read(buffer) > 0)
// End timing
我想您会发现它几乎与解析文本的时间完全相同。
请注意,您还应该为InputStreamReader
提供适当的编码 - 几乎可以肯定,平台默认编码不是您应该使用的。
【讨论】:
亲爱的乔恩,我已经测试了时间。时间仅用于 while 循环 @Shashi:是的,因为那是它实际从网络读取的地方。除非这些行很大,否则这真的不会是 BufferedReader / InputStreamReader 开销。以上是关于使用 BufferedReader.readLine() 读取 inputStream 太慢的主要内容,如果未能解决你的问题,请参考以下文章
在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?
Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)