Java编程中的编码问题(转)
编码方式的简介:
String序列化成byte数组或反序列化时需要选择正确的编码方式。如果编码方式不正确,就会得到一些0x3F的值。常用的字符编码方式有ISO8859_1、GB2312、GBK、UTF-8/UTF-16/UTF-32。
ISO8859_1用来编码拉丁文,它由单字节(0-255)组成。
GB2312、GBK用来编码简体中文,它有单字节和双字节混合组成。最高位为1的字节和下一个字节构成一个汉字,最高位为0的字节是ASCII码。
UTF-8/UTF-16/UTF-32是国际标准UNICODE的编码方式。 用得最多的是UTF-8,主要是因为它在对拉丁文编码时节约空间。
UNICODE值 UTF-8编码
?
???? (2)以Jsp-charset编码方式解释jsp文件中出现的字符,并将其转化成Unicode编码,再转化成UTF-8格式,存为.java文件,编译生成.class文件。
???? (3)运行.class文件,在服务器内部以Unicode格式对字符进行运算处理。
???? (4)将运行后的结果转化为Jsp-charset格式输出到浏览器,并告诉浏览器该页面编码格式为Jsp-charset,如果未指定Jsp-charset,则同样取默认值,大多数web服务器的默认值是:ISO8859-1。
???? (5)浏览器收到结果,根据Jsp-charset自动选择对应的方式( <meta?http-equiv=content-type?content="text/html; charset=gb2312">
)查看。如Jsp-charset为GBK,则浏览器自动以“简体中文”方式查看;如Jsp-charset为ISO8859-1,则浏览器自动以“西欧”方式查看。
看一段简单的jsp代码:
?????? <%
??????????? out.println("汉语");?
??????? %>
??????? “汉语”两个字的GBK编码为:0xBABAD3EF
???????? 对应的Unicode编码为:?????? 0x6C498BED
???????? 用UTF-8表示为:???????????????? 0xE6B189E8AFAD。
当jsp源文件中指定Jsp-charset为GBK时,“汉语”的编码转化过程如下:
???????? jsp源文件中为:?????????????????? 0xBABAD3EF
??????? .java和.class文件中为:??????? 0xE6B189E8AFAD
???????? 在内存中运行时为:???????????? 0x6C498BED
???????? 输出到浏览器时为:???????????? 0xBABAD3EF
???????? 浏览器根据Jsp-charset=GBK自动选择以“简体中文”方式查看结果,得到“汉语”的正确显示。当jsp 源文件指定Jsp-charset为ISO8859-1时,“汉语”两个字在jsp源文件中的编码0xBABAD3EF,被当作ISO8859-1格式处 理,由于ISO8859-1是单字节编码的,因此转化成Unicode格式就成了:0x00BA00BA00D300EF,用UTF-8表示为: 0xC2BAC2BAC393C3AF。编码转化过程如下:
???????? jsp源文件中为:?????????????????? 0xBABAD3EF
??????? .java和.class文件中为:??????? 0xC2BAC2BAC393C3AF
???????? 在内存中运行时为:???????????? 0x00BA00BA00D300EF
???????? 输出到浏览器时为:???????????? 0xBABAD3EF
???????? 浏览器根据Jsp-charset=ISO8859-1自动选择用“西欧”方式查看结果,结果是0xBABAD3EF在ISO8859-1中对应的字符串 “ooó?”;如果手动改变浏览器的查看方式为“简体中文”,则能得到“汉语”的正确显示。当jsp源文件不指定Jsp-charset时,大多数服务器 默认Jsp-charset为ISO8859-1,转化过程和指定Jsp-charset为ISO8859-1相同。值得一提的是,把Jsp- charset指定为GBK和指定为ISO8859-1,只要浏览器以“简体中文”方式查看都能得到“汉语”的正确显示。这是因为在编译jsp源文件时, 是将字符编码格式从Jsp-charset转化成Unicode,当输出到浏览器时,又将Unicode转化成Jsp- charset,这两步是相互抵消的。有人可能会问:以上是将jsp源文件保存为GBK格式,如果将jsp源文件保存为其他格式,如UTF-8或是 ISO8859-1会是什么结果呢?其实过程原理是一样的,值得说明的是,普通的文本编辑器不能指定保存格式,当源文件中含有中文字符时它会自动保存为 GBK格式。有些高级IDE,如eclipse,能指定保存格式,但是当你将含有中文字符的jsp源文件保存为ISO8859-1时,它会提示你不能保 存,因为源文件中含有与ISO8859-1不兼容的字符,如果将含有中文的jsp源文件保存为UTF-8格式,则eclipse会自动将其中的中文字符转 化成Unicode,再转化成UTF-8格式保存,比如“汉语”保存为UTF-8格式为:0xE6B189E8AFAD。
???????? 当jsp源文件指定Jsp-charset为UTF-8时,此时如果jsp源文件是GBK格式的,则无论怎样都得不到正确的显示,只有将jsp源文件保存 为UTF-8格式才能得到正确的结果,即一般必须正确指定jsp源文件的编码方式。某些情况下,比如实际是GBK,指定编码ISO8859-1也不会错。 UTF-8转化过程如下:?
???????? jsp源文件中为:?????????????? 0xE6B189E8AFAD
??????? .java和.class文件中为:??? 0xE6B189E8AFAD
???????? 在内存中运行时为:???????? 0x6C498BED
???????? 输出到浏览器时为:???????? 0xE6B189E8AFAD
浏览器根据Jsp-charset=UTF-8自动选择用“Unicode(UTF-8)”方式查看结果,得到“汉语”的正确显示。
???????
?????? 3、HTML表单提交汉字处理。
?????? 有一个基本的事实是表单中的字符通过http协议传给服务器,http无一例外的使用ISO8859-1为传输对象的编码方式。因此客户端通过表单提交的字符数据到达服务器的时候是ISO8859-1编码,需要把它使用.getBytes("ISO-8859?-1","file.encoding")进行显示的转换才能正确的显示出来。如:
???? String?username?=?new?String?(userLoginForm.getUsername().getBytes("ISO-8859?-1","gb2312");
???????
???????4、JDBC与数据库(以MySQL为例)汉字处理。
? ???? 在获得数据库连接的时候,需要指定以unicode方式处理字符,并且接收的字符是file.encoding编码的,即与jsp页面中的jsp-charset保持一致,或者.java文件的实际编码方式一致。如:
??????? DriverManager.getConnection("jdbc:mysql://localhost/webstore?useUnicode=true&
characterEncoding=gb2312","root", "");??
??????? 在mysql数据里设置字符集为GB2312.
??????? create database webstore character set 'gb2312';
????????
???????? create table `user` (
??????? `user_id` INTEGER(11) NOT NULL AUTO_INCREMENT,
??????? `user_name` VARCHAR(10) NOT NULL,
??????? `user_password` VARCHAR(10) NOT NULL,
??????? `user_level` INTEGER(1) NOT NULL,
???????? PRIMARY KEY (`user_id`)) CHARACTER SET 'gb2312';