一、编码乱码
-
英文
无论是Unicode还是GBK,英文编码都是一致的 -
中文
不同字符集间编码不一致,甚至是表示一个字符的字节数都不一致,所以就会出现很多的乱码问题。 -
程序中
强力推荐使用UTF-8编码
1、常见中文编码及字节数
GBK(两个字节)
GB_2312(两个字节)
Unicode(四个字节)
UTF-8(三个字节)
不同编码不但占用的字节数不同,字节编码也不相同!
程序世界能不用中文就不用中文,只能出现在两个地方:注释和字符串
2、为什么不用一个字节表示一个汉字
因为汉字太多了,表示不过来,一个字节表示的范围是0~255,最多能表示256个字符。光是常用的就有2000多个,所以一个字节存储不过来。
英文编码呢,比如LATIN_1字符集,一个字节(256个字符)可以表示西欧国家的文字的字符集,不存在乱码问题
3、编码之间的瓜葛
一个字节表示汉字不够,那如果使用两个字节表示汉字呢?
两个字节0~65535,存储汉字够了(5万多个)
那为什么UTF-8编码要3个字节,unicode编码使用4个字节,GBK使用2个字节,为什么不统一
其实最早出现的中文编码是GBK和GB2312字符集,是中国人自己制定的汉字编码,占用两个字节。Windows是全世界使用最多的PC操作系统,是最早研发中文操作系统的,由于历史原因,一直延续使用的是GBK字符集。
后来,国际化标准组织想要发明一个能够表示世界上所有国家语言文字的字符集(Unicode组织),就有了UTF-8和Unicode编码。UTF-8中一个中文字符占用三个字节,而Unicode编码是可变长度的(1~4个字节,一般是4个字节),使用频率越高的占用的字节越少,使用频率越低的语言,占用的字节越多。
Unicode字符集仅仅是字符的表示编码,并未规定表示编码如何存储到计算机中,由此引出了UTF-8编码。UTF-8是Unicode编码在计算机中的存储编码,UTF-8编码中,一个汉字占用3个字节,一个英文一个字节。
我们在程序中程序中尽量使用UTF-8编码,Windows默认的是GBK编码,程序中能不出现中文就尽量不要使用中文,中文只允许出现在注释和字符串中,养成良好的编程习惯
4、Servlet乱码问题解决方案
- request.setCharacterEncoding(“UTF-8”)修改,不推荐,每次都要设置,太麻烦
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
- 使用过滤器,推荐,一劳永逸
package org.westos.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import java.io.IOException;
//凡是过滤器,value = "/*",过滤所有的
@WebFilter(description = "EncodingFilter", value = "/*", initParams = {@WebInitParam(name = "encoding", value = "UTF-8")})
public class EncodingFilter implements Filter {
private String encoding;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.encoding =filterConfig.getInitParameter("encoding");
}
//过滤器在过滤请求的时候,一定会执行doFilter方法,将请求和响应的字符集都设置为UTF-8
//过滤器过滤的是请求
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//给请求和响应设置为UTF-8编码
servletRequest.setCharacterEncoding(this.encoding);
servletResponse.setCharacterEncoding(this.encoding);
//过滤器链条,确保继续向后过滤
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
- 也可以在xml配置文件中进行配置