《深入分析Java WEB技术内幕》第三章深入分析Java Web中的中文编码问题

常用编码格式

ASCII

总共128个,用一个字节的第7位表示,0~31是控制字符,32 ~126是打印字符

ISO-8859-1

256字符,单字节编码,涵盖绝对大多数西欧编码

GB3212

中文编码字符集,双字节编码,A1~A9符号区,B0 ~F7汉字区,包含6763个汉字

GBK

汉字内码扩展规范
为了拓展GB3212,加入更多汉字,与GB2312兼容

UTF-16

Unicode,统一码,试图包含世界中所有的编码。UTF-16用两个字节来表示Unicode的转化格式,采用定长表示法,Java就是以UTF-16作为内存的字符存储格式

UTF-8

由于UTF-16是以两个字节来表示一个字符,大多数字符只需要一个字节就够了,UTF-8采用一种变长的技术,每个编码区域有不同的字码长度,不同类型可由1~6字节组成。
规则是,如果1个字节,则最高位为0,表示一个ASCII码;如果有一个11开头的,则连续的1的个数则暗示这个字符的字节数;如果一个字节,以10开始,表示它不是首字节,则需要向前查找才能得到当前字符的首字节。
可见UTF-8验证

在Java中需要编码的场景

IO操作中

在字节->字符,一般使用InputStreamReader,它是委托StreamDecoder去完成的,它需要由用户指定Charset,如果没有指定则默认使用本地环境的字符集。
输出也是一样的。
注意输入时,与输出的时的编码解码得保持一致。

在内存中编码

在内存中实现字符到字节的转换。
比如"dasdasdas".getBytes("UTF-8");

在Java中如何编码

可见默认的是UTF-8(主要还是因为本机系统编码格式是UTF-8,如果是Windows的话,就是GBK了)
在这里插入图片描述
可以看出中文字符在ISO编码中全是3f对应的解码就是?
而UTF-16中,所有的字符都扩容到两个字节来编码。
从String->byte主要是以上几个步骤:
1.0String变为StringCoding:1.getBytes(charsetName)
1.1 encode: 根据指定编码格式编码
1.2 查询Charset:lookupCharset->Charset.forName: 查找编码格式的编码规则
1.3 根据查找到的编码格式新建StringEncoder对象
1.4 创建编码对象和解码对象。
2.通过编码器转换为byte数组

总结

GBK汉字范围大于GB2312
UTF-16编码效率较高,适用于本地磁盘和内存之间使用,网络传输效率不高。
UTF-8适用于网络传输,是最理想的中文编码格式。

常见问题

1.编码解码不对应
2.一个问号,中文字符用了不支持中文的编解码
3.两个问号,经历了不支持中文的编码,再用双字节编码格式
4.System.out.println(new String(new String(name.getBytes("GBK"),"ISO-8859-1").getBytes("ISO-8859-1"),"GBK"));这样子是合法的,只要中间只要按照其他解编码顺序,且成对。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值