我创建了一个小型的抓取类,下面的方法从页面中读取文本。
但是,我发现该方法无法正确关闭连接。这导致大量的打开连接,导致我的托管公司暂停我的帐户。以下是正确的吗?
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;
}
答案 0 :(得分:2)
您的代码在成功案例中没有问题但在故障情况下可能会泄漏连接(当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()
该连接,除非您确定在不久的将来不再有该主机上的网址请求 - disconnect()
将阻止后续请求通过在现有连接上进行流水线操作,特别是对于https来说,这将大大减慢速度。
答案 1 :(得分:1)
您只是关闭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) {}
}