JavaWeb技术内幕三:JavaWeb中文编码问题

  1. 云栖社区>
  2. 博客>
  3. 正文

JavaWeb技术内幕三:JavaWeb中文编码问题

黄小斜 2018-08-05 11:19:46 浏览616
展开阅读全文
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a724888/article/details/81429274

微信公众号【Java技术江湖】一位阿里 Java 工程师的技术小站。(关注公众号后回复”Java“即可领取 Java基础、进阶、项目和架构师等免费学习资料,更有数据库、分布式、微服务等热门技术学习视频,内容丰富,兼顾原理和实践,另外也将赠送作者原创的Java学习指南、Java程序员面试指南等干货资源)

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

Java作为跨平台语言,涉及到的编解码问题也比较多,我们来探讨一下HTTP请求如何控制编码格式。

几种常见的编码格式

为什么要编码

由于计算机只能看懂01,人类只能看懂字符,所以要进行编码和解码。

1 在计算机中,一个字节是最小的信息存储单元,而一个字节只能表示256个字符。

2 人类需要的符号远远超过256个。

如何翻译

各种语言需要交流,如何进行翻译呢,在计算机中提供了常见的翻译方式。比如ASCII,UTF-8等编码方式,他们可以被看做字典,可以让字节数组变成对应的字符。那么他们有什么区别呢。

1 ASCII码
一共有128个,用一个字节的低七位表示。

2 ISO

128个字符显然不够用,于是在ASCII基础上建立了ISO-8559编码。虽然仍是单字节,但可以表示256字符。

3 GB2312

是双字节编码,可以表示6763个汉字

4 GBK

它扩展了GB2312,功能表示21003个汉字。他和GB2312相互兼容

5 UTF-16

首先说下Unicode,ISO试图简历一个超语言词典,让所有语言都可以通过这个字典翻译。这是非常复杂的。

UTF-16定义了Unicode字符在计算机中的存储方法,UTF-16用两个字节来表示Unicode的转化格式,并且使用定长的方法,无论什么字符都可以用2个字节表示。

这大大简化了字符串操作,所以Java使用UTF-16作为内存字符的存储格式。

6 UTF-8
UTF-16统一使用两个字节表示一个字符,虽然很简单,但是很多字符只需要一个字节就可以表示了,相当于多处用了一倍的空间。

在网络带宽有限的情况下,没有必要。UTF-8使用变长技术,每个编码区有不同的字码长度。所有字符可以用1-6个字节组成。

如果是一个字节的字符那么就是ASCII码了

Java中需要编码的场景

io操作中存在的编码

字节流到字符流的互相转换需要用到编码

内存操作中的编码

使用String字符串和byte数组进行相互转换时,需要指定编码

Java中如何编解码

一般指定charsetname为指定编码格式即可。

各种编码实践

对几种编码格式的比较

1 对于中文字符,使用GBK好一点

2 对于Unicode字符,使用UTF-16的编码效率较高,转换更简单,进行字符串操作也更好,适合在磁盘和内存之间使用,但是不适合进行网络传输,因为双字节容易损坏,且占用空间大。

3 UTF-8更适合网络传输,UTF-8使用单字节存储,单个字符损坏不影响其他字符。

Java Web中设计的编解码

对于http网络传输,考虑压缩数据,减少网络传输量,但是有的压缩算法只减少字符数但是不减少字节数。

在计算机中,汉字的表示方式一般是一个字符使用两个字节来表示,所以Java的char类型也是16个bit,也就是2个字节。

JavaWeb可能出现编码转换的地方:

1 HTTP请求中的URI,Cookie,Post表单参数需要解码。

2 数据库的读写,文件读写需要编解码。

3 所有数据从socket返回时需要编码,浏览器解析页面需要解码。

URL的编解码

一个URL可以被分为好多个组成部分

http://localhost:8080/hello/servlet/黄蓬龙?name=h2pl

scheme domain port context servletpath pathinfo querystring

这部分中,url不包括querystring,uri则只包括hello/servlet/黄蓬龙,也就是context+servletpath+pathinfo。

所以uri只是定位资源,但是不包括网络协议

对于Tomcat而言,servlet会把这个url解析为一下几个部分。
事实上一部分配置是在server.xml配置文件中定义的。

1 port是配置文件中的connector port定义的。

2 context path是在配置文件中定义的

3 servletpath是web.xml的url-pattern中定义的。

4 pathinfo是我们具体请求的servlet

5 querystring是要传递的参数

pathinfo采用utf-8编码,querystring采用gbk编码

总结就是,url的编解码过程比较复杂,不是我们在应用中能控制的,所以尽量避免在url中使用非ASCII字符。

HTTP header的编解码

同理,默认使用ISO编码且不能改变,所以不用有非ASCII字符。

POST表单的编解码

post使用body传递数据,而header中设置了contenttype,所以我们根据这个编码格式进行编解码即可。

http body的编解码

上面讲过了。

另外JDBC的编码设置要和数据库内置的数据编码保持一致。

在JS中的编码问题

外部引入JS文件

引入时需要设置编码,否则可能乱码

JS的URL编码

其他需要编码的地方

1 xml可以设置头指定编码格式

2 velocity模板设置编码

3 jsp设置编码

常见问题分析

中文字符变乱码

编码解码的字符集不一致

一个汉字变成问号

将中文经过ISO编码(不支持中文)后会变成?

一个汉字变成两个问号

可能是多次编码过程中出错。

不正常的正确编码

网友评论

登录后评论
0/500
评论
黄小斜
+ 关注