从ResourceBundle获取字符串乱码,尝试Utf8Control仍未解决
解决Java本地化ResourceBundle读取乱码问题
看起来你已经找对了核心方向(自定义Utf8Control),但问题出在重复转码和可能的文件编码配置细节上,咱们一步步来修复:
1. 核心问题:重复转码导致二次乱码
你自定义的Utf8Control已经通过InputStreamReader(stream, "UTF-8")正确用UTF-8解码了properties文件内容,这时候messages.getString(key)拿到的已经是正常的Java字符串(Java内部用UTF-16存储,不存在编码问题)。但你后续又执行了:
String message = new String(messages.getString(key).getBytes("ISO-8859-1"), "UTF-8")
这相当于把正确的字符串先转成ISO-8859-1字节(非ASCII字符会丢失或损坏),再转成UTF-8,反而制造了乱码。这一步必须删掉。
2. 修正后的业务代码
保留你的Utf8Control类,修改业务代码如下:
Locale locale = new Locale(language); ResourceBundle messages = ResourceBundle.getBundle("i18n.messages", locale, new Utf8Control()); try { // 直接获取字符串,无需额外转码 String message = messages.getString(key); pageContext.getOut().write(message); } catch (IOException e) { e.printStackTrace(); }
3. 确保properties文件的实际编码是UTF-8
即使你提到"文件默认编码为ISO-8859-1",也要确认以下细节:
- 你的
.properties文件是实际以UTF-8编码保存的(可以用记事本/VS Code等工具打开,查看并切换编码) - 不要带UTF-8 BOM(BOM会导致ResourceBundle加载异常,大部分编辑器默认不会添加,但要注意排查)
- 如果用IDE(比如IDEA/Eclipse),要把properties文件的编码设置为UTF-8,并且关闭"自动转Unicode转义"的选项(比如IDEA里的
Transparent native-to-ascii conversion,这个选项是给默认ISO-8859-1加载逻辑用的,和自定义Utf8Control冲突)
4. 确认JSP的编码配置完整
除了pageEncoding="UTF-8",还要确保JSP的contentType明确指定字符集,在JSP开头添加:
<%@ page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>
另外,建议检查Web容器(比如Tomcat)的server.xml,确保Connector配置了URIEncoding="UTF-8"(避免后续请求参数的编码问题):
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8"/>
5. 验证排查步骤
可以在代码里加一行控制台打印,确认ResourceBundle加载的原始字符串是否正确:
String rawMessage = messages.getString(key); System.out.println("Raw message: " + rawMessage); // 控制台应输出正确字符
- 如果控制台输出正确,但JSP页面乱码:问题出在JSP的编码配置或Web容器的输出编码
- 如果控制台就乱码:问题出在properties文件编码或
Utf8Control的加载逻辑
内容的提问来源于stack exchange,提问作者Nico_99
相关产品推荐
相关产品推荐

