以汉字‘中国’为例html
咱们常常在开发中会遇到以下几种java
从这里几个编码开始提及吧web
\u4e2d\u56fd ,咱们常常在后台的配置文件中看到,好比message 文件,它表示的字符在unicode编码中对应的数字。spring
因为java内部采用unicode编码,能够经过下面的代码来获取。浏览器
String str1 = "\u4e2d\u56fd"; System.out.println(str1); System.out.println(Integer.toHexString('中')); 输出 中国 4e2d
%E4%B8%AD%E5%9B%BD, 这类编码 ,常常在get请求的url中看到,用于传递表单数据,显示的数据实际上就是字符的UTF-8的值,每一个字节前加上%tomcat
经过以下代码来验证网络
byte[] aa = "中国".getBytes("utf-8"); for(int i=0; i<aa.length;i++) { System.out.print(String.format("%02x",aa[i]).toUpperCase()); } 输出 E4B8ADE59BBD
看到这里,可能会有一个疑惑,就是unicode怎么转换为utf-8的,4e2d怎么变成E4B8AD的,下面来讲说这个问题。字体
unicode是编码方案,4e2d 描述的是‘中’在编码表对应的数字,但并不涉及如何在字节中展现它。ui
utf的的全称(Unicode Transformation Formats),从字面能够理解,它描述的是unicode编码在字节中的存储了。编码
UTF-8 规则以下
0xxxxxxx
这样作的好处是,utf-8向下兼容ascii编码。
第一个字节前n位设置为1,第n+1位设置为0 ,后面字节前2为都设置为10,其余空余位 由unicode 编码来填充,高位补0
110xxxxx 10xxxxxx 1110xxxx 10xxxxxx 10xxxxxx 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
拿刚才的中的例子来讲
4E2D转换为二进制位为 0100111000101101
在UTF-8中须要使用3个字节来表示 1110xxxx 10xxxxxx 10xxxxxx
将4E2D填充到x中后 表示为 11100100 10111000 10101101
转换为十六进制为 E4B8AD
中国 中国 这种很少见,实际上也就是unicode的值,它本质我理解为html的转义字符,咱们可能会在html中看到它。20013 和 4E2D 就是十进制和十六进制,其实都是同样的。
咱们知道,一个字节范围是0-255,ascii在表示字符时,使用了0-127。而中文字符因为数量多,须要由两个以上的字节去表示一个字符。
每种编码集,都将字符映射到了不一样的字节去表示,好比港台的BIG5 大陆的GBK,国际规范的unicode等。之前有款软件叫作magicwin,基本98,95下玩游戏必备,就是转换字体的字符集的。
咱们开发中,出现乱码常常是IO环节出现,好比读写文件,网络通信等。
实际上这个过程经历了 String ->byte -> String。
好比咱们在通信或文件操做时,传输和保存的本质都是字节流,而在字符到字节转换的过程当中,须要按照一致的编码解码进行处理,不然就会产生乱码
以下图所示
上图就是 gbk编码的中国 在解码时被转换成了乱码
须要注意的几点
WEB环境下,主要是浏览器->TOMCAT容器->具体项目代码
出现乱码可能在如下两个点
WEB环境下乱码的本质是网络IO的乱码,浏览器是客户端,而 tomcat是服务端,产生的缘由对应以下:
主要因为涉及到浏览器,容器之类的,形成对于编码不太透明,会让人疑惑。
常见的处理方式:
浏览器在发起get请求时,会进行encodeURI,将汉字转换为%E4%B8%AD%E5%9B%BD, 而tomcat在默认解析时,会按照iso8859-1去处理,因此常常会出现一些request.getParameter() 获取的字符串为乱码。
这个处理最好全局的去修改tomcat 的配置文件为URIEncoding="UTF-8" ,不然须要对字符串进行一个iso8859-1 -> utf-8的转换。
网页在解析html文件时,会按照声明的字符集进行解析
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
若是不设置,会自动选择字符集进行处理,每一个浏览器默认的不一致。
保持声明的一致就能够避免乱码
常见的方式 设置统一的filter 进行处理。
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>