GBK,UTF-8,和ISO8859-1之间的编码与解码

Unicode、UTF-8 和 ISO8859-1到底有什么区别

将以"中文"两个字为例,经查表可以知道其GB2312编码是"d6d0 cec4",Unicode编码为"4e2d 6587",UTF编码就是"e4b8ad e69687"。注意,
这两个字没有iso8859-1编码,但可以用iso8859-1编码来"表示"。

2. 编码基本知识

最早的编码是iso8859-1,和ascii编码相似。但为了方便表示各种各样的语言,逐渐出现了很多标准编码,重要的有如下几个。

2.1. iso8859-1 通常叫做Latin-1

属于单字节编码,最多能表示的字符范围是0-255,应用于英文系列。比如,字母a的编码为0x61=97。

很明显,iso8859-1编码表示的字符范围很窄,无法表示中文字符。但是,由于是单字节编码,和计算机最基础的表示单位一致,所以很多时候,
仍旧使用iso8859-1编码来表示。而且在很多协议上,默认使用该编码。比如,虽然"中文"两个字不存在iso8859-1编码,以gb2312编码为例,应
该是"d6d0 cec4"两个字符,使用iso8859-1编码的时候则将它拆开为4个字节来表示:"d6 d0 ce c4"(事实上,在进行存储的时候,也是以字节为
单位处理的)。而如果是UTF编码,则是6个字节"e4 b8 ad e6 96 87"。很明显,这种表示方法还需要以另一种编码为基础。

2.2. GB2312/GBK

这就是汉子的国标码,专门用来表示汉字,是双字节编码,而英文字母和iso8859-1一致(兼容iso8859-1编码)。其中gbk编码能够用来同时表示
繁体字和简体字,而gb2312只能表示简体字,gbk是兼容gb2312编码的。

2.3. unicode

这是最统一的编码,可以用来表示所有语言的字符,而且是定长双字节(也有四字节的)编码,包括英文字母在内。所以可以说它是不兼容iso8859-1编
码的,也不兼容任何编码。不过,相对于iso8859-1编码来说,uniocode编码只是在前面增加了一个0字节,比如字母a为"00 61"。

需要说明的是,定长编码便于计算机处理(注意GB2312/GBK不是定长编码),而unicode又可以用来表示所有字符,所以在很多软件内部是使用unicode
编码来处理的,比如java。

2.4. UTF

考虑到unicode编码不兼容iso8859-1编码,而且容易占用更多的空间:因为对于英文字母,unicode也需要两个字节来表示。所以unicode不便于传输和存
储。因此而产生了utf编码,utf编码兼容iso8859-1编码,同时也可以用来表示所有语言的字符,不过,utf编码是不定长编码,每一个字符的长度从1-6个字
节不等。另外,utf编码自带简单的校验功能。一般来讲,英文字母都是用一个字节表示,而汉字使用三个字节。

注意,虽然说utf是为了使用更少的空间而使用的,但那只是相对于unicode编码来说,如果已经知道是汉字,则使用GB2312/GBK无疑是最节省的。不过另
一方面,值得说明的是,虽然utf编码对汉字使用3个字节,但即使对于汉字网页,utf编码也会比unicode编码节省,因为网页中包含了很多的英文字符。

3. java对字符的处理

在java应用软件中,会有多处涉及到字符集编码,有些地方需要进行正确的设置,有些地方需要进行一定程度的处理。

3.1. getBytes(charset)

这是java字符串处理的一个标准函数,其作用是将字符串所表示的字符按照charset编码,并以字节方式表示。注意字符串在java内存中总是按unicode编码
存储的。比如"中文",正常情况下(即没有错误的时候)存储为"4e2d 6587",如果charset为"gbk",则被编码为"d6d0 cec4",然后返回字节"d6 d0 ce c4"。
如果charset为"utf8"则最后是"e4 b8 ad e6 96 87"。如果是"iso8859-1",则由于无法编码,最后返回 "3f 3f"(两个问号)。

3.2. new String(charset)

这是java字符串处理的另一个标准函数,和上一个函数的作用相反,将字节数组按照charset编码进行组合识别,最后转换为unicode存储。参考上述getBytes
的例子,"gbk" 和"utf8"都可以得出正确的结果"4e2d 6587",但iso8859-1最后变成了"003f 003f"(两个问号)。

因为utf8可以用来表示/编码所有字符,所以new String( str.getBytes( "utf8" ), "utf8" ) === str,即完全可逆。

3.3. setCharacterEncoding()

该函数用来设置http请求或者相应的编码。

对于request,是指提交内容的编码,指定后可以通过getParameter()则直接获得正确的字符串,如果不指定,则默认使用iso8859-1编码,需要进一步处理。
参见下述"表单输入"。值得注意的是在执行setCharacterEncoding()之前,不能执行任何getParameter()。java doc上说明:This method must be called prior to reading request parameters or reading input using getReader()。而且,该指定只对POST方法有效,对GET方法无效。分析原因,应该是在执行第一个getParameter()的时候,java将会按照编码分析所有的提交内容,而后续的getParameter()不再进行分析,所以setCharacterEncoding()无效。而对于GET方法提交表单是,提交的内容在URL中,一开始就已经按照编码分析所有的提交内容,setCharacterEncoding()自然就无效。

4.iso-8859-1是JAVA网络传输使用的标准 字符集,而gb2312是标准中文字符集,当你作出提交表单等需要网络传输的操作的时候,就需要把 iso-8859-1转换为gb2312字符集显示,否则如果按浏览器的gb2312格式来解释iso-8859-1字符集的话,由于2者不兼容,所以会 是乱码.

最后来看一个编码的例子:

[java] view plaincopyprint?

  1. String s = "你好";
  2. // 编码
  3. byte[] utf = s.getBytes("utf-8");
  4. byte[] gbk = s.getBytes("gbk");
  5. System.out.println("utf-8编码:" + Arrays.toString(utf)); // [-28, -67, -96, -27, -91, -67]  6个字节
  6. System.out.println("gbk编码:" + Arrays.toString(gbk)); // [-60, -29, -70, -61]<span style="white-space:pre">  </span>4个字节
  7. // 解码
  8. String s1 = new String(utf, "utf-8"); // 你好
  9. String s2 = new String(utf, "gbk");// gbk解码:浣犲ソ gbk用2个字节解码,所以会多一个字符
  10. String s3 = new String(gbk, "utf-8");// gbk用utf-8解码:??? <span style="white-space:pre">  </span>utf-8解码需要6个字节
  11. System.out.println("--------------------");
  12. System.out.println("utf-8解码:" + s1);
  13. System.out.println("gbk解码:" + s2);
  14. System.out.println("gbk用utf-8解码:" + s3);
  15. System.out.println("---------------------");
  16. System.out.println("用utf-8编码回去");
  17. s3 = new String(s3.getBytes("utf-8"), "gbk");  // 锟斤拷锟?   gbk用utf-8解码后无法编回去
  18. System.out.println(s3);

规律:

utf-8编码可以用gbk和iso8859-1解码后编回去
gbk编码后只能用iso8859-1解码后编回去

在JSP页面获取表单的值时会出现乱码,有两种解决方法:

一种是在调用getParameter之前通过request.setCharacterEncoding设置字符编码,另一种是调用new String(str.getBytes("iso8859-1"), "UTF-8");编码后解码,这两种方法都可以得到正确的结果

时间: 2024-10-25 15:40:23

GBK,UTF-8,和ISO8859-1之间的编码与解码的相关文章

浏览器正确理解和使用GBK及UTF-8(UTF-8 + BOM)网页编码

网页编码英文译为web page encoding,是在网页中指定其特定的字符编码格式的库. GBK是国家标准GB2312基础上扩容后兼容GB2312的标准.GBK的文字编码是用双字节来表示的,即不论中.英文字符均使用双字节来表示,为了区分中文,将其最高位都设定成1.GBK包含全部中文字符,是国家编码,通用性比UTF8差,不过UTF8占用的数据库比GBK大. UTF-8:Unicode TransformationFormat-8bit,允许含BOM,但通常不含BOM.是用以解决国际上字符的一种

python3 unicod,utf-8,gbk的编码和解码中文显示问题

python3的字符编码让人头疼.这个也不是一篇介绍gbk, utf-8, unicode怎么表示英文,中文字符的基础知识总结.网上有很多类似的文章,目前也不需要升入学习到了解各个bit位表示什么含义. 目的:清楚了解为什么在python3不同的编码,解码,windows,linux操作系统下,字符是否能够正确显示. 前提:了解不同编码用不同的二级制编码和长度来表示字符.在python3中,各种字符编码之间的互相转换都要通过unicode作为中间编码转换.gbk转换成unicode,再从unic

mysql与服务器之间的编码问题

1.之前在练习一个java web的项目时,mysql的编码设置正确,服务器的编码也设置正确,但向mysql中存储数据时,就会出现乱码问题,后来发现是mysql与服务器之间的编码设置问题,以下是mysql的目录,复制my-default.ini该文件,并且命名为my.ini,这样根目录下就有两个.ini文件了,一个是my-default.ini,一个是my.ini . 2.接下来我们只需修改my.ini里面的内容就行了 在[mysqld]下面添加 character_set_server=utf

tomcat服务器乱码问题,tomcat与数据库之间的编码统一转换

在tomcat目录的conf目录下,修改server.xml文件,在下面截图中的位置加上URIEncoding="UTF-8"则表示tomcat编码转换为utf-8风格, 一般在前台获得相应的值后都会处理编码问题,如用String 类的转码,URLEncoder等转码以至于传到数据库不会乱码 tomcat服务器乱码问题,tomcat与数据库之间的编码统一转换

python编码:gbk编码与解码

gbk编码与解码: >>> a='\xce\xc4\xbc\xfe\xb5\xbd\xb4\xef\xb3\xc9\xb9\xa6' #gbk编码后的数据 >>> a '\xce\xc4\xbc\xfe\xb5\xbd\xb4\xef\xb3\xc9\xb9\xa6' >>> b=a.decode('gbk') #gbk解码 >>> b u'\u6587\u4ef6\u5230\u8fbe\u6210\u529f' >>&

编码和解码(字符串与byte[]之间的转换)

资源来自互联网http://www.cnblogs.com/dabaopku/archive/2012/02/27/2370446.html 非常蛋疼的事情, google 和 baidu 在编码是分别采用了 UTF-8 和 GB2312 基础知识 UTF-8中,一个汉字对应三个字节,GB2312中一个汉字占用两个字节. 不论何种编码,字母数字都不编码,特殊符号编码后占用一个字节. public static string MyUrlDeCode(string str, Encoding enc

ASCII、GBK、unicode、utf-8、iso-8859-1等编码的发展史和相互关系

1.ASCII 很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同的状态,以表示世界上的万物.他们认为8个开关状态作为原子单位很好,于是他们把这称为"字节". 再后来,他们又做了一些可以处理这些字节的机器,机器开动了,可以用字节来组合出更多的状态,状态开始变来变去.他们看到这样是好的,于是它们就这机器称为"计算机". 开始计算机只在美国用.八位的字节一共可以组合出256(2的8次方)种不同的状态. 他们把其中的编号从0开始的32种状态分别规定了特殊的

对GBK的理解(内附全部字符编码列表)

由于GB 2312-80只收录6763个汉字,有不少汉字,如部分在GB 2312-80推出以后才简化的汉字(如“啰”),部分人名用字(如中国前总理朱镕基的“镕”字),台湾及香港使用的繁体字,日语及朝鲜语汉字等,并未有收录在内.于是厂商微软利用GB 2312-80未使用的编码空间,收录GB 13000.1-93全部字符制定了GBK编码. 其使用范围如下(注意是汉字编码表,不包括符号编码): 表1 汉字编码范围 名称 第一字节 第二字节 GB2312 0xB0-0xF7(176-247) 0xA0-

JAVA与mysql之间的编码问题

之前一直没有自己动手配置过数据库所以也一直没有发现这个问题,百度了一下发现网络上并没有相应的解决方案,于是我开始自己摸索的解决这个问题. 问题状况大致是这样的,在数据库中存在一个表,当我在java代码中删除表中的元祖的时候没有办法根据中文的属性值删除对应元祖.可能表述的不是很准确,接下来我配合图片进行说明吧. 工具/原料 mysql eclipse navicat 方法/步骤  一般出现在这种问题都是因为数据库和编译环境使用的编码不一样的造成的,为了方便说明我举个学生信息表为例吧. 比如现在存在