`
tiantianfei
  • 浏览: 38355 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

深入剖析JAVA编程中的中文问题

阅读更多
JAVA中文编码问题
先介绍一个概念:本地编码,所谓本地编码是操作系统采用的中文编码格式,一般是“GBK”或“GB2312”,可以用System.getProperty("file.encoding")。

本文从以下几个方面来对JAVA中的中文编码进行说明。
1.中文存储方式
2.编码变换问题
3.解决方法

第一:中文存储方式
本部分分控制台应用,WEB应用来分析:
对控制台应用:
JAVA文件--->CLASS文件---->虚拟机- - - >控制台输出
本地编码     UTF-8         UTF-8       本地编码
编辑源文件并保存,中文以本地编码方式保存, 利用javac编译后中文以UTF-8方式存在与类文件中,程序运行时,中文也是以UTF-8的格式存在,进行相关处理后,在控制台输出时,再从UTF-8转换为本地编码显示在控制台上.

对WEB应用:
JSP文件--->临时Servlet文件--->Servlet类文件--->虚拟机
本地编码 本地编码(缺省) UTF-8 UTF-8

WEB应用中客户端与服务器数据交互:
客户端---->传递---->服务器---->传递---->GBK
GBK ISO-8859-1 GBK ISO-8859-1 GBK
用户在表单中输入汉字时,编码格式肯定是本地编码,在发送之前IE把中文转换成ISO-8859-1,再发送到服务器,服务器接收到ISO-8859-1格式码流后,再变换成本地编码,服务器进行处理后,如果返回到客户端的是中文,也需要先变换成ISO-8859-1,然后再传递到客户端,客户端再用本地编码进行解释并显示。

数据库应用:
JAVA文件--->CLASS文件---->虚拟机- - - >传递
本地编码 UTF-8 UTF-8 本地编码
缺省在程序与数据库之间传递数据是以ISO-8859-1方式,JDBC首先把UNICODE格式的串转化为ISO-8859-1,然后传递到数据库,数据库进行处理后,把GBK编码的中文首先编码成ISO-8859-1再返回到客户端。

第二:编码变换问题
中文(不管是GBK还是GB2312),英文(ISO-8859-1),UTF-8三种不同的字符集之间存在映射表,通过映射表可以实现彼此之间的转换。可以实现中文<->英文、中文->UTF-8、英文UTF-8之间的变换,中英文到UTF-8的转换主要是虚拟机实现的。变换的过程就是编码和解码的过程,比如从中文”世界“转换成UTF-8格式,”世界“的中文编码为0xCAC0BDE7,在类文件和虚拟机中的编码为0xE4B898E7958C,在中文与UTF-8的映射表中肯定存在这么一项,如果在程序中有如下代码:
1. String str = "世界";//在虚拟机中的形式为0xE4B898E7958C
2. byte[] buf = str.getBytes("GBK");//编码,从UTF-8为GBK,buf中存放的肯定是0xCAC0BDE7
3. System.out.println(str); //控制台输出
4. System.out.println(new String(buf)); //解码为中文”世界“并显示
5. buf = str.getBytes("ISO-8859-1"); //编码,从UTF-8到ISO-8859-1,此时出现问题
6. System.out.println(new String(buf)); //解码为中文,显示 ??,说明出现了编码错误
7. System.out.println(new String(buf, "ISO-8859-1")); //编码为ISO-8859-1,显示 ??,说明出现编码错误
第5行代码出现问题,因为目前内存中的UNICODE 0xE4B898E7958C是从GBK的0xCAC0BDE7转换过来的,如果编码成ISO-8859-1,在UTF-8<->ISO-8859-1的映射表中根本不存在该表目,所以在该行开始出现编码错误。如果显示的是??肯定是编码错误,如果是乱码,往往是显示问题。此时,无论如何也不能由buf中的数据再变换到正确的编码。

第三:解决方法
解决中文编码问题的大原则就是:编解码必须保持一致。
比如程序中第2行就是从UTF-8编码到中文(GBK),跟前面的从中文(GBK)解码为UTF-8保持一致。也就是先从0xCAC0BDE7到0xE4B898E7958C,然后在第2行,再由0xE4B898E7958C到0xCAC0BDE7,此时控制台可以正确显示中文。即便没有第2行代码,那么在控制台显示前,控制台会先完成虚拟机中的0xE4B898E7958C到0xCAC0BDE7的转换,再进行显示。
在WEB开发中,为避免中文问题,可考虑采用如下方法:
在Servlet的doGet和doPost方法中:
request.setCharacterEncoding("GB2312"); //设置输入编码格式
response.setContentType("text/html;charset=GB2312");//设置输出编码格式
在JSP中:
<%@page contentType="text/html;charset=GBK"%>
<%request.setCharacterEncoding("GBK");%>
在数据库编程时,要首先保证数据库使用的是中文编码、另外再需要时设置数据库连接的编码格式为中文。
只要你全面掌握了中文的源文件、类文件、虚拟机和传输过程中的编码格式,并牢记编解码一致的原则,相信你能解决所有的中文问题。

网友:忽略了java文件自身也是可以指定编码方式

网友:源文件的编码格式不能指定,只能用操作系统缺省的编码格式.当然在编译的时候可以用-encoding选项来指定类文件的中文编码格式.
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics