必须指定正确字符编码,优先从http响应头content-type提取charset,其次解析html meta标签,最后才退至系统默认编码;用该编码构造inputstreamreader并套bufferedreader读取。

直接用 InputStreamReader 包装 URLConnection 的 InputStream 是可行的,但关键在于**必须指定正确的字符编码**,否则容易乱码——网页的 charset 通常由 HTTP 响应头或 HTML meta 标签声明,不能默认用平台编码。
先获取并识别网页真实编码
很多网页在 Content-Type 响应头中明确声明了 charset,比如 text/html; charset=UTF-8。应优先从响应头提取:
- 调用
connection.getContentType(),再用正则或字符串解析提取charset=xxx - 若响应头未声明,可读取前几 KB HTML 内容,查找
<meta charset="UTF-8">或<meta http-equiv="Content-Type" content="text/html; charset=GBK"> - 万不得已时才退回到
InputStreamReader默认编码(通常是系统 defaultCharset),但不推荐
用指定编码构造 InputStreamReader
拿到编码名(如 "UTF-8" 或 "GBK")后,传给 InputStreamReader 构造函数:
URLConnection conn = url.openConnection(); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); InputStream is = conn.getInputStream(); String charset = detectCharset(conn); // 上一步识别出的编码 InputStreamReader reader = new InputStreamReader(is, charset);
⚠️注意:不要写成 new InputStreamReader(is) —— 这会使用平台默认编码,中文网页极易乱码。
配合 BufferedReader 高效读取文本
InputStreamReader 是字符流桥接器,本身不带缓冲。生产环境建议套一层 BufferedReader 提升性能:
- 用
new BufferedReader(reader)包装 - 然后调用
readLine()逐行读取,或read(char[])批量读取 - 记得在 finally 或 try-with-resources 中关闭
BufferedReader(它会自动关闭底层 reader 和 stream)
完整示例(含异常与资源管理)
推荐用 try-with-resources 确保流正确释放:
URL url = new URL("https://example.com");
URLConnection conn = url.openConnection();
conn.connect();
String charset = detectCharset(conn); // 自定义方法,返回如 "UTF-8"
try (InputStream is = conn.getInputStream();
InputStreamReader reader = new InputStreamReader(is, charset);
BufferedReader br = new BufferedReader(reader)) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
不复杂但容易忽略编码匹配,实际项目中建议复用成熟的 HTTP 客户端(如 OkHttp、Apache HttpClient),它们已内置 charset 自动探测和解码逻辑。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











