Java 中文乱码解决方案汇总

Java 中文乱码解决方案汇总 (2009-07-24 08:16:10)


花掉了整整一个下午, 读了 sun, ibm, csdn, javaeye 几个网站相关资料共 12 篇, 把 Java 开发中目前可能遇到的中文乱码问题及解决方案总结了一下, 记下备忘.

//********************
// 一、可能出现的乱码
//********************

1. 包含中文内容的 JSP 页面在浏览器中显示不正确.
2. servlet 无法正确解析 POST 方式提交的中文内容.
3. servlet 无法正确解析 GET 方式提交的中文内容.
4. servlet 向 response 回送的中文内容显示不正确.
5. 读/写数据库时中文内容不正确.
6. 桌面应用程序界面中的中文显示不正确.
以上各种情况下, 凡是涉及显示的, 中文字符有可能显示为 ? 或方块


//********************
// 二、乱码产生的原因
//********************

  首先, 此问题的根源来自计算机字符编码方式的繁杂和标准的不统一, 由于世界各地语言文字不尽相同, 出现此问题是必然的.
其实, Java 的文件存储/编译机制, JVM 的工作机制, 在实现中内部都采用了统一的 unicode 编码方式, 若目标平台解码方式不一致, 便会出现中文乱码(实际上不仅是中文, 多/单字符集都有可能出问题, 视目标平台而不同).

  关于字符集编码的详细分析, 内容太多, 不再转述, 在 ibm, unicode.org 等官方网站中, 可以找到几篇非常深入的资料. 此处只为记录解决方案.


//************************
// 三、避免乱码的通用原则
//************************
  有一些通用的原则, 在编程中应该遵守, 可以免去一些初级的麻烦:

1. JSP:
  a. JSP 文件中, 应指定 contentType, 其中 charset 的值要与客户端浏览器所用的字符集一样.
  b. 对于其余的字符串常量, 不需做任何内码转换.
  c. 对于字符串变量, 要能根据 ContentType 中指定的字符集还原成客户端能识别的字节流, 因为字符串变量是 "基于 <Jsp-charset> 字符集的".

2. Servlet:
  a. Servlet 中, 应通过 HttpServletResponse.setContentType() 将 charset 设置为与客户端内码一致.
  b. 字符串常量, 需要在 Javac 编译时指定 encoding 为与编写源文件的平台的字符集一样, 对于中文环境一般说来都是 GB2312 或 GBK.
  c. 字符串变量, 类似 JSP, 必须是 "基于 <Servlet-charset> 字符集的".


//************************************
// 四、针对各种乱码问题的具体解决方案
//************************************
以下解决方案假定目标平台是中文平台, 测试环境为:

操作系统 : Windows Vista 版本 6.0 运行于 x86 上; GBK; zh_CN (nb), Ubuntu 8.04
浏览器  : IE 7, FireFox 3
Java 环境 : Java 2 SDK 1.6.0_10-rc; Java HotSpot(TM) Client VM 11.0-b15
应用服务器 : Apache Tomcat 6.0
开发环境 : NetBeans IDE 6.1

类型1. “包含中文内容的 JSP 页面在浏览器中显示不正确”
-------------------------------------------------
问题描述: 一个 JSP 文件在浏览器中打开时, 中文内容显示为 ? 和方块.

解决方案1: 在 .jsp 文件中指定编码方式.

示例:
<[email=[ft=,,Verdana]%@page]%@page[/email] contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<META http-equiv=Content-Type content="text/html; charset=UTF-8">

说明:
将编码方式指定为 UTF-8
修改后, 中文字符在浏览器中显示正常.

类型2. servlet 无法正确解析 POST 方式提交的中文内容(同样适用于 .jsp 嵌入脚本)..
----------------------------------------------------------------------------
问题描述: 通过 form 以 POST 方式向 servlet 提交数据时, servlet 中得到的中文内容不正确. (通过测试可证明, 并非是输出时不正确, 而是获取到的内容本身不正确, 问题 3 同).

解决方案1: 在 Servlet 中指定编码方式.

示例:
在 doPost() 方法中作以下调用.
response.setContentType( "text/html; charset=UTF-8" ); // 设置 content-type
response.setCharacterEncoding( "UTF-8" );  // 设置响应数据编码格式 (输出)
request.setCharacterEncoding( "UTF-8" );  // 设置请求数据编码格式 (输入), 此处是关键

说明:
通常我们会用 PrintWriter out = response.getWriter(); 来获取 out 对象, 如果是这样, 那此调用必须放在上述调用之后.
之后调用 request.getParameter() 取到的参数, 不必再作任何转换.

解决方案2: 通过 filter 实现通用编码过滤.

示例:
创建一个 filter, 继承自 HttpServlet, 并实现 Filter 接口.
在 doFilter() 方法中, 将截获的 request 内容进行编码转换.
测试代码根据 Tomcat 的 filter-example 修改通过, 比较长, 在此不列出了.

说明:
如果项目中涉及编码转换的模块较多, 可用此方法.
此 filter 需实现一个继承自 HttpServletRequestWrapper 的具体类, 可利用 hashmap 结构重载 getParameterValues() 等方法.

解决方案3: 编写单独的转换函数(方法).

说明:
此方法原理跟方案2一样, 转换函数很简单, 只需要用 getBytes( "ISO8859-1", "UTF-8" ) 转换即可.
此方法适用于模块较少的情况.

类型3. servlet 无法正确解析 GET 方式提交的中文内容(同样适用于 .jsp 嵌入脚本).
--------------------------------------------------------------------------
问题描述: 通过地址栏 URL 以 GET 方式向 servlet 提交数据时, servlet 中得到的中文内容不正确.

解决方案1: 参照类型 2 的解决方案.

说明: GET 方式的这个问题, 由于跟应用服务器和浏览器发送 URL 的方式相关, 在不同的设置下, 有可能无效, 可再尝试下面的方案.

解决方案2: 修改 Tomcat 配置.

示例:
修改 %tomcat_home%/conf/server.xml
在 <Connector port="8080" protocol="HTTP/1.1"... 段内加入 URIEncoding="GBK", 重启 Tomcat 后生效.

说明:
此方法经测试有效. 但 server.xml 设置影响 Tomcat 管理的所有应用程序, 如果有别的不同编码的应用存在, 应慎用此方法.

类型4. servlet 向 response 回送的中文内容显示不正确.
-------------------------------------------------
参照类型 2 的解决方案1, 设置正确的 content-type 即可.

类型5. 读/写数据库时中文内容不正确.
--------------------------------
不同数据库上的解决方案不同, 但原理相同, 即: 指定数据库使用的字符集, 或在读/写时进行编码转换, 或二者结合使用.

5.1 MySQL:
MySQL 的默认编码为 latin1, 与 ISO8859-1 相同, 涉及中文数据时需要转换.

5.1.1.插入中文:(不用编码)
String sql = "INSERT INTO 表名 (字段名) VALUES('" + request.getParameter( "字段名" ) + "')";
stmt.executeUpdate( sql );

5.1.2.显示读出的中文:
因为存入的是 Latin1, 显示需要转换.
String str = new String(( rs.getString( "字段名" )).getBytes( "ISO8859_1" ), "UTF-8" );
out.println( str );

5.1.3 直接设定字符集编码方式:
Connection conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/jsp?useUnicode=true&characterEncoding=UTF-8", "root", "" );
str = "中文内容";
String sql = "INSERT INTO 表名 (字段名) VALUES('" + str + "')";

5.2 其他数据库 (未经测试, 暂不列出)

6. 桌面应用程序界面中的中文显示不正确.
---------------------------------------
说明:
任何涉及字符串显示的地方(常量, 变量), 均应考虑到不同编码的目标平台. 可以将与界面显示相关的资源提取出来到放入资源文件 ResourceBundle(ListResourceBundle, PropertyResourceBundle).
当程序需要处理这些资源时, 从 ResourceBundle 里将需要的本地化资源装入.
需要注意的是: 为了能够正确显示中文字符, 程序里的部件需要选择指定字体, 例如在显示中文的时候使用 "SimSun", 不然界面有中文字符的时候会显示为方框.
(此节未经测试)

7. 上传文件时的乱码
--------------------
问题描述: 上传文件时, 接收到的中文数据不正确.

解决方案1: 升级标准组件.

说明:
上传时 form 设置的都是 enctype="multipart/form-data".
浏览器将以流方式提交文件, 如果使用 apach 的上传组件, 会有乱码情况. 这是因为 apache 的先期 commons-fileupload.jar 有 bug, 取出汉字后进行解码, 因为这种方式提交, 编码又自动使用的是 Tomcat 缺省编码格式 ISO8859-1.
可下载 commons-fileupload-1.1.1.jar (或更新版本) 的 jar, 已经解决了这些 bug.
但是取出内容时仍然需要对取出的字符进行从 ISO8859-1 到 UTF-8 转码.
自行编写的上传组件, 对编码的处理参照上述各点.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值