必须显式指定字符编码,优先从content-type头提取charset,否则默认编码可能导致乱码;推荐用standardcharsets.utf_8,并用try-with-resources确保inputstream、inputstreamreader和bufferedreader正确关闭。

直接用 InputStreamReader 包装 URLConnection 返回的 InputStream 即可,但关键是要**显式指定字符编码**,否则可能因平台默认编码不一致导致乱码。
必须指定正确的字符编码
InputStreamReader 默认使用 Charset.defaultCharset()(如 Windows 上常为 GBK),而网页或 API 响应通常声明为 UTF-8。若不指定,中文等非 ASCII 字符极易出错。
- 优先从响应头获取编码:
connection.getContentEncoding()不可靠,应看Content-Type中的charset=,例如text/html; charset=UTF-8 - 若响应头未明确指定,再参考 HTML 或 XML 的 meta 声明(需额外解析),或按服务约定(如 REST API 通常用 UTF-8)
- 最稳妥做法:显式传入
StandardCharsets.UTF_8(Java 7+)
基本转换写法(推荐 UTF-8)
以打开一个网页为例:
URL url = new URL("https://example.com");
URLConnection connection = url.openConnection();
InputStream is = connection.getInputStream();
// ✅ 正确:指定 UTF-8
InputStreamReader reader = new InputStreamReader(is, StandardCharsets.UTF_8);
后续可用 BufferedReader 提升读取效率:
BufferedReader br = new BufferedReader(reader);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
从 Content-Type 动态提取编码(更健壮)
如果服务端正确设置了响应头,可自动提取:
String contentType = connection.getContentType(); // e.g. "text/html; charset=UTF-8"
String charset = "UTF-8"; // fallback
if (contentType != null) {
int i = contentType.indexOf("charset=");
if (i != -1) {
charset = contentType.substring(i + 8).trim();
// 清理掉可能的分号或引号,如 "UTF-8;" 或 "UTF-8"
charset = charset.split("[;\s"]")[0];
}
}
InputStreamReader reader = new InputStreamReader(is, Charset.forName(charset));
注意资源释放与异常处理
InputStreamReader 本身不持有底层连接,但 InputStream 和后续的 BufferedReader 都需关闭:
- 建议用 try-with-resources 自动关闭
- 不要只关
InputStreamReader,要确保InputStream(即URLConnection.getInputStream())也被释放 - 网络请求可能抛出
IOException、MalformedURLException等,需捕获或声明抛出
完整示例:
URL url = new URL("https://httpbin.org/get");
try (InputStream is = url.openConnection().getInputStream();
InputStreamReader reader = new InputStreamReader(is, StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(reader)) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
不复杂但容易忽略编码细节Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











