有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使用InputStreamReader和BufferedReader缓慢读取HTTP响应?

我有以下Java代码,它向web服务器发送HTTP请求并读取响应:

StringBuilder response = new StringBuilder(50000);
URL url2 = new URL(ServiceURL); 
connection = (HttpURLConnection)url2.openConnection();
connection.setRequestMethod("POST");

//... (some more connection settings) ...

BufferedWriter  wr = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream(), "UTF-8"));

wr.write(Request);
wr.flush ();
wr.close ();

InputStream is = connection.getInputStream();       
BufferedReader rd = new BufferedReader(new InputStreamReader(is));

int i = 0;
while ((i = rd.read()) > 0) {
    response.append((char)i);
}

它适用于大多数情况,但我有一个问题,一台服务器返回一个相当大的XML(大约500KB;我想这对于一堆文本来说是相当大的),我一直收到读取超时异常

我相信这不是网络问题,因为我尝试过使用curl发出相同的请求,但响应很快就到达了,大约两秒钟

当我查看网络中发生的事情(使用wireshark捕获数据包)时,我注意到我的计算机中的TCP接收窗口在某个时刻变得满了。TCP协议栈有时会在这种情况下幸存下来;我可以看到服务器发送TCP keep alive以保持连接,但最终TCP连接中断

可能是代码的读取部分(一个字符接一个字符地追加接收到的响应)让我的代码变慢了吗?有没有更有效的方法来读取HTTP响应


共 (2) 个答案

  1. # 1 楼答案

    一个字一个字地读是很慢的。尝试一次将块读入缓冲区:

    char[] buf = new char[2048];
    int charsRead;
    while((charsRead = rd.read(buf, 0, 2048)) > 0) {
        response.append(buf, 0, charsRead);
    }
    
  2. # 2 楼答案

    正如菲尔已经说过的,逐字节读取流有点慢。我更喜欢使用BufferedReader的readLine()方法:

    StringBuilder response = new StringBuilder();
    String line = "";
    while((line = rd.readLine()) != null) {
        response.append(line + System.getProperty("line.separator");
    }
    
    如果可能的话,我会考虑使用Apache HTTP客户端库。它易于使用,在处理HTTP内容时非常强大。 http://hc.apache.org/httpcomponents-client-ga/

    您还应该记住设置插座和连接超时。通过这种方式,您可以控制连接保持打开的时间(至少在连接的您一侧)

    最后但并非最不重要的一点是,在收到响应后,始终在finally块中关闭HTTP连接,否则可能会遇到打开文件过多的问题

    希望这是heps;)