开发中常见的编码和乱码问题

以汉字‘中国’为例

我们经常在开发中会遇到如下几种

  • \u4e2d\u56fd
  • %E4%B8%AD%E5%9B%BD
  • 中国 中国

从这里几个编码开始说起吧

1 unicode字符串

    \u4e2d\u56fd  ,我们经常在后台的配置文件中看到,比如message 文件,它表示的字符在unicode编码中对应的数字。

    由于java内部采用unicode编码,可以通过下面的代码来获取。

String str1 = "\u4e2d\u56fd";
System.out.println(str1);
System.out.println(Integer.toHexString('中'));

输出
中国
4e2d

 

2 URL Encoder

%E4%B8%AD%E5%9B%BD, 这类编码 ,经常在get请求的url中看到,用于传递表单数据,显示的数据实际上就是字符的UTF-8的值,每个字节前加上%

通过如下代码来验证

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的,下面来说说这个问题。

3 unicode和utf-8

unicode是编码方案,4e2d 描述的是‘中’在编码表对应的数字,但并不涉及如何在字节中展示它。

utf的的全称(Unicode Transformation Formats),从字面可以理解,它描述的是unicode编码在字节中的存储了。

UTF-8 规则如下

  1. 对于ascii字符,第一位为0,后面的x由ascii来填充

        0xxxxxxx

        这样做的好处是,utf-8向下兼容ascii编码。

  2.   对于其他字符,通过可变字节来表示

           第一个字节前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

 

4 html字符实体

&#20013;&#22269; &#x4E2D;&#x56FD; 这种不多见,实际上也就是unicode的值,它本质我理解为html的转义字符,我们可能会在html中看到它。20013  4E2D 就是十进制和十六进制,其实都是一样的。

 

5 乱码的产生

    我们知道,一个字节范围是0-255,ascii在表示字符时,使用了0-127。而中文字符由于数量多,需要由两个以上的字节去表示一个字符。

    每种编码集,都将字符映射到了不同的字节去表示,比如港台的BIG5 大陆的GBK,国际规范的unicode等。以前有款软件叫做magicwin,基本98,95下玩游戏必备,就是转换字体的字符集的。

    我们开发中,出现乱码经常是IO环节出现,比如读写文件,网络通讯等。

    实际上这个过程经历了 String ->byte -> String。

    比如我们在通讯或文件操作时,传输和保存的本质都是字节流,而在字符到字节转换的过程中,需要按照一致的编码解码进行处理,否则就会产生乱码

如下图所示

  

上图就是  gbk编码的中国  在解码时被转换成了乱码

需要注意的几点

  1. 避免多次编码或解码。
  2. 注意操作系统、虚拟机环境的默认编码

 

6 WEB环境下的乱码

WEB环境下,主要是浏览器->TOMCAT容器->具体项目代码

出现乱码可能在以下两个点

  1. 表单提交的数据产生乱码
  2. 网页显示乱码

WEB环境下乱码的本质是网络IO的乱码,浏览器是客户端,而 tomcat是服务端,产生的原因对应如下:

  1. 当浏览器提交的数据,后台解码不正确时,后台会产生乱码
  2. 当浏览器解析后台返回的数据时,编码解码不一致,网页可能会显示乱码。

主要由于涉及到浏览器,容器之类的,造成对于编码不太透明,会让人疑惑。

常见的处理方式:

  1.  get请求的乱码

        浏览器在发起get请求时,会进行encodeURI,将汉字转换为%E4%B8%AD%E5%9B%BD, 而tomcat在默认解析时,会按照iso8859-1去处理,所以经常会出现一些request.getParameter() 获取的字符串为乱码。

        这个处理最好全局的去修改tomcat  的配置文件为URIEncoding="UTF-8" ,否则需要对字符串进行一个iso8859-1 -> utf-8的转换。

  2. 网页显示的字符集设置

    网页在解析html文件时,会按照声明的字符集进行解析

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

    如果不设置,会自动选择字符集进行处理,每个浏览器默认的不一致。 

    保持声明的一致就可以避免乱码

  3. POST请求的乱码

        常见的方式 设置统一的filter 进行处理。

 <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

 

 

 

转载于:https://my.oschina.net/u/988317/blog/1490346

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值