【问题标题】:BufferedReader connection doesn't closeBufferedReader 连接未关闭
【发布时间】:2014-06-11 07:46:30
【问题描述】:

我创建了一个小型抓取类,下面的方法从页面中读取文本。

但是,我发现该方法无法正确关闭连接。这会导致大量打开的连接导致我的托管公司暂停我的帐户。以下是正确的吗?

private String getPageText(String urlString) {

    String pageText = "";


        BufferedReader reader = null;
        try {
            URL url = new URL(urlString);
            reader = new BufferedReader(new InputStreamReader(url.openStream()));
            StringBuilder builder = new StringBuilder();
            int read;
            char[] chars = new char[1024];
            while ((read = reader.read(chars)) != -1)
                builder.append(chars, 0, read); 

            pageText = builder.toString();
        } catch (MalformedURLException e) {
            Log.e(CLASS_NAME, "getPageText.MalformedUrlException", e);
        } catch (IOException e) {
            Log.e(CLASS_NAME, "getPageText.IOException", e);
        } finally {
            if (reader != null)
                try {
                    reader.close();
                } catch (IOException e) {
                    Log.e(CLASS_NAME, "getPageText.IOException", e);
                }
        }
        return pageText;


}

【问题讨论】:

  • 您应该先关闭 URL 连接(即,与url.openStream 相反)。
  • 你知道怎么做吗?我无法使用自动完成功能找到它。
  • 我认为下面的答案(@epoch)显示了如何做得很好......
  • 根据documentation 阅读器关闭与其关联的所有资源。所以我认为你的代码是正确的。
  • @cy3er,阅读器与输入流相关联,而不是连接

标签: java bufferedreader


【解决方案1】:

您的代码在成功情况下很好,但在失败情况下可能会泄漏连接(当 http 服务器返回 4xx 或 5xx 状态代码时)。在这些情况下,HttpURLConnection 通过.getErrorStream() 而不是.getInputStream() 提供响应正文,您还应确保排空并关闭该流。

URLConnection conn = null;
BufferedReader reader = null;
try {
  conn = url.openConnection();
  reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
  // ...
} finally {
  if(reader != null) {
    // ...
  }
  if(conn instanceof HttpURLConnection) {
    InputStream err = ((HttpURLConnection)conn).getErrorStream();
    if(err != null) {
      byte[] buf = new byte[2048];
      while(err.read(buf) >= 0) {}
      err.close();
    }
  }
}

最终可能需要在其中添加另一层 try/catch,但您明白了。您应该明确地.disconnect() 连接,除非您确定在不久的将来该主机上不会再有对 url 的请求 - disconnect() 将阻止后续请求通过管道传输现有的连接,尤其是对于 https 会大大减慢速度。

【讨论】:

    【解决方案2】:

    您只是关闭stream 而不是connection,使用以下结构:

    URL u = new URL(url);
    HttpURLConnection conn = (HttpURLConnection)
            u.openConnection();
    conn.connect();
    
    reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
    

    然后:

    } finally {
        if (reader != null)
           try {
               reader.close();
           } catch (IOException e) {
               Log.e(CLASS_NAME, "getPageText.IOException", e);
           }
        }
    
        try {
            if (conn != null) {
                conn.disconnect();
            }
        } catch (Exception ex) {}
    }
    

    【讨论】:

    • 你的意思是说我必须添加一个HttpURLConnection而我没有?
    • 愚蠢的问题:你能有一个流但没有连接吗?
    • 是的,尽管仍然在内部建立连接,但正如文档所述,调用 openStream 与调用 openConnection().getInputStream() 相同
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-18
    • 2016-06-09
    • 2016-08-07
    • 1970-01-01
    • 2012-08-08
    相关资源
    最近更新 更多