java编码格式


一、编码格式

1、ASC码表:美国信息标准交换码(这是最初的一个表,其中的字母用各种各样的数字进行代替)。

2、GB2312:中国汉字的编码表(里面收录了几千个中国常用汉字和字符)。

3、GBK:GB2312的扩容版(里面收录了两万多的中国汉字,因为中国汉字博大精深)。

4、18030表:相当于GBK的扩容版(里面收录了各个民族的字,后期会讲到)。

5、Unicode表:将世界上所有的语言中的文字进行的整合,所产生的一个表(里面无论什么字符都用两个字节进行表示,也就是16个二进制位)

6、UTF-8表:Unicode表进行优化之后的一个表(该使用一个字节的用一个字节,该用两个或者三个的用两个或者三个)。

二、UTF-8编码格式
1、概述:
和别的表不一样,utf-8表有“表头”,会自动辨别是用3个字节还是2个字节存储一个字符。java默认使用的是Unicode编码形式,UTF-8的全称是:Unicode Transform Format - 以最小8为单位

2、注意:
在使用中国平常的编码表GBK的时候,如果转换成utf-8的话,可能会出现错误,乱码之类的东西,因为数值对应的汉字不相同。

三、GBK和UTF-8的编码格式转换
 String s="哈哈哈"; //字符串
 byte[] b=s.getBytes("gbk");  //指定编码格式是gbk转换成字节数组
 System.out.println(Arrays.toString(b)); //按照gbk的编码格式转换成字符串之后,输出一下字节数组,看看是什么样的形式
 String s1=new String(b,"UTF-8"); //将上面用gbk编码的字节数组用utf-8解码格式进行解码,输出的字符串自己才能看懂
 System.out.println(s1);  
  
 代码第二部分,按照以上的格式进行编码,但是同样出错:
  
 byte[] b1=s1.getBytes("UTF-8");  //将上面的s1字符串用utf-8编码格式进行编码
 System.out.println(Arrays.toString(b1)); //输出一下用utf-8编码格式的字节数组
 String s2=new String(b1,"gbk"); //将上面的用utf-8编码格式的字节数组进行解码
 System.out.println(s2);  //输出一下用utf-8解码之后的String类型的字符串

 /*
  * 为什么下面的代码经过错误编码之后还是出现乱码呢?
  * 答案:因为gbk编码格式和utf-8编码格式同样都支持中文,所以会出现乱码!!!
  * 这样就不难理解了吧
  * */ 

四、编码格式转换
在开发的过程中,经常会遇到各种各样编码错误的问题。

比方说:
在中国经常使用的gbk格式编码,但是tomcat服务器使用的是iso8859-1编码格式,只认识英文,因为是老美那帮伙计编写的,没有办法。这个时候就需要编码格式的转换。一般在浏览器中使用的资料的提交,如果是使用的是get方法提交的话,如果浏览器的编码格式和tomcat的编码格式不相同的话,只能进行编码格式的二次转换,就是说:在服务器端只能编一次,再解一次。如果使用的是post方法提交的话,可以通过服务器当中一个对象的函数setCharactorEncoding设定字符编码,指定gbk,自动帮我转换。

解决办法:
为什么不让tomcat直接指定编码格式为gbk啊?当然这个是完全可以的,但是你想一想,一个服务器可以同时部署很多个网站,有的网站使用的是这个编码格式,有的网站使用的是哪个编码格式,如果都统一使用gbk,那么你访问网站的时候,会出现意想不到的乱码,所以如果想要让全球统一的话,只有两种方法,一种是继续使用ios8859-1编码格式,一种是中国统一世界,然后统一使用gbk编码格式,相对于第一种,我比较喜欢第二种大笑

五、“编码”&“解码"
字符串变字节数组:编码(将自己“知道”的内容变成“不知道”的内容,但是让机器明白是什么东西,就是编码)
字节数组变字符串:解码(将自己“不知道”的内容变成“知道”的内容,但是让机器不明白是什么东西,就是解码)

六、“联通”和“蔚”问题
发现一个”有意思“的问题,就是创建一个文本文件,在里面写入“联通”,保存退出,再打开文件,会出现乱码!从同学那儿借鉴过来的内容:

1、ASCII的霸权:
起初,是一些人想用8个晶体的亮灭表示世间万物,于是产生了“编码”,最早是美国人发明了ASCII字符集(American Standard Code for Information Interchange,美国信息互换标准代码)用来存储英文字符,一个字节8位,可以表示2^8=256个符号,其中0~32特殊用途(0x20以下);32~127 存储 英文;128~255为扩展字符集;

2、GB2312的来历:
中国人想用电脑读写汉字,256个字符不够用怎么办?于是果断舍弃127之后没用的字符,并且在ASCII的基础上规定如果一个字符小于127则表示原字符,即所谓的半角字符,如果连续两个字符大于127则表示一个汉字,即全角字符。这就是GB2312,它实际是ASCII的中文扩展。后来又有了GBK,GB18030,都是对汉字字符集的扩充。

3、UNICODE的大一统:
一个叫 ISO (国际标谁化组织)的国际组织决定用16位来表示地球上所有文字,于是产生传说中的"Universal Multiple-Octet Coded Character Set",简称 UCS, 俗称 "UNICODE"。它规定两个字节为一个字符,英文高8位都是0,但问题是GBK 与UNICODE 在汉字内码编码完全不同。这为谣言埋下了伏笔....

4、UTF8的传输:
互联网上70%的内容是英文,而UNICODE英文高8位为0,如果采用UNICODE传输无疑造成空间浪费,于是产生UTF8即每次8个位传输数据,当然还有UTF16,UTF32,都是按一定规则转化后的编码形式。

5、总结:
这样就可以解释记事本不能显示的问题了,实际上,“联通”这两个字符的GBK编码具有UTF-8编码的特征,记事本犯下的错误正是将GBK编码存放的记录有“联通”两个字符的文件误认为UTF-8编码的文件。

6、细节:
UTF-8编码采用1-3个字节对字符进行编码,编码字节数与字符的Unicode编码值有严格的对应关系,让我们回忆下UTF-8编码和Unicode的对应关系吧。
Unicode编码值 UTF-8编码结构
\u0001 - \u007E 0XXXXXXX
\u0080 - \u07FF 和 \u0000 110XXXXX 10XXXXXX
\u0800 - \uFFFF 1110XXXX 10XXXXXX 10XXXXXX
“联通”这两个字符的GBK编码值是“C1 AA CD A8",GBK编码方式使用两个字节对一个字符进行编码,因此以GBK编码方式存放的录有“联通”两个字符的文件的大小为四个字节。接下来分别观察“联通”这两个字符GBK编码值的二进制形式,你有发现有趣的事。
联 GBK 十六进制:C1 AA 二进制:1100 0001,1010 1010
通 GBK 十六进制:C1 AA 二进制:1100 1101,1010 1000

请注意上面二进制数据的部分,你想到了什么?对,它们和UTF-8编码结构中的补充位完全一致,UTF-8编码的补充位使得编码值更有规律,而记事本刚好凭借这个特征区分UTF-8编码的文件。存有“联通”两个字符的文件的所有数据都符合这个特征,就是这样,记事本彻底的将文件误认为UTF-8编码的文件。将错就错,让我们来看看这个错误是怎样收场的。如果把“联通”的GBK编码值当作UTF-8编码值,那文件就成为一个写有数据“C1 AA CD A8”并以UTF-8编码的文件,当使用记事本再次打开的时候会看到什么呢?只要将UTF-8编码转换成Unicode编码就知道了。UTF-8编码“C1 AA CD A8”转换成Unicode编码后,编码值为“6A 00 68 03”(转换方法请参考本Blog中的《字符编码》一文)。0x006A这个Unicode编码值位于\u0001 - \u007E之间,若要转换为UTF-8编码,显然只能用一个字节进行编码,因此“联”的GBK编码“C1 AA”虽然特征上貌似UTF-8编码,但它却不对应任何一个UTF-8编码。接着看0x0368这个Unicode编码值,这个值对应了字符“?”,这也正是我们将在记事本中看到的内容。或许你会说我看到的是一个黑色矩形啊,这只是字体的原因,你将字体改为宋体或者其他字体,看到的就是字符“?”。对于中文字符,UTF-8编码要用三个字节进行编码,因此,如果你使用记事本录入“联通”,然后选择以UTF-8编码方式保存的话,文件大小应为9个字节(包含三个字节的开头数据),而同样的文件GBK编码却是4个字节。

7、扩展:
实际上,不仅是”联通“有问题,输入”蔚蓝“的”蔚“也会出现翻译出错的问题,所以这个问题应该不是个案了!
七、小程式演示:

package com.itheima;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.util.Arrays;

public class BianMaDemo {

	/**
	 * @param args
	 * @throws UnsupportedEncodingException 
	 */
	public static void main(String[] args) throws UnsupportedEncodingException {
		// TODO Auto-generated method stub
		String s="哈哈哈";
		byte[] b=s.getBytes("gbk");		//指定编码格式编码
		System.out.println(Arrays.toString(b));//将字符改成了字节数组
		String s1=new String(b,"UTF-8");	//指定解码格式解码
		System.out.println(s1);
		/*
		 * 为什么下面的代码经过错误编码之后还是出现乱码呢?
		 * 答案:因为gbk编码格式和utf-8编码格式同样都支持中文,所以会出现乱码
		 * 这样就不难理解了吧
		 * */
		byte[] b1=s1.getBytes("UTF-8");
		System.out.println(Arrays.toString(b1));
		String s2=new String(b1,"gbk");
		System.out.println(s2);
	}

}


 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值