version 1.0
一、【声明】
编码三大概念:字符库;编码字符集;字符编码【转换关系】
GB2312、GB18030:国家标准
GBK:是继承于(兼容)GB2312的扩展方案[目前:非国家标准];GBK >> GB2312
UTF-8的汉字数量:少于GB18030
GBK包含全部中文字符;UTF-8则包含全世界所有国家需要用到的字符[来源:知乎]
UTF-8与GBK:GBK包含中国全部汉字;UTF-8:有利于国际化[俗称:万国码]
Windows系统:优先支持UTF-16;而非UTF-8
二、【参考文档】
0.【十分钟搞清字符集和字符编码】(https://linux.cn/article-5027-1.html) //经典文章[本文必读]
1.【HTML <form> accept-charset 属性】(http://www.w3school.com.cn/tags/att_form_accept-charset.asp);
2.【tomcat 的编码设置?】(https://my.oschina.net/u/224202/blog/56102)
3.【url的三个js编码函数escape(),encodeURI(),encodeURIComponent()简介】(http://www.haorooms.com/post/js_escape_encodeURIComponent);
4.【JavaScript(js) 前台 参数传递乱码 转码 问题--已解决! 中文字符乱码】 (http://blog.csdn.net/hurryjiang/article/details/6960298);//escape;encodeURI;encodeURIComponent
三、【关于编码与转码的操作总结】
Web容器端:
1.【URIEncoding】server.xml内所在端口的connector中配置URIEncoding = "目标字符集"【默认:ISO-8859-1】
2.【useBodyEncodingForURI】server.xml内所在端口的connector中配置:useBodyEncodingForURI="true"
数据库:
1.MySQL:创建数据库时候,设置采用UTF8MD5[alter database databaseName set character = utf8md5]
2.MySQL: 修改mysql在windows\my.ini里default-character-set=utf-8
服务器端:
0.文件外部设置文件的编码
1.指令
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> //经常使用:
备注:此处的contentType="text/html; charset=UTF-8"比meta元素中的优先级高;故web容器优先采用此处的设置
2.网页文件内部设置:<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
3.request:
[only one about set file's character]
request.setCharacterEncoding("字符集");//经常使用
4.对中文参数进行URL转码:java.net.URLEncoder("中文参数","GBK/UTF-8/..."); //推荐使用
5.response:
response.setCharacterEncoding("字符集"); //经常使用
response.setContentType("text/html;charset=utf-8");//经常使用
response.addHeader("content-type", "text/html;charset=utf-8");
response.addHeader("Content-Type", "application/pdf");
response.setHeader("content-type", "text/html;charset=utf-8");//经常使用
response.setHeader("refresh", "5;URL=www.xxxx.com");
response.setHeader("Pragma", "no-cache");
response.encodeRedirectURL("字符集");//经常使用
response.encodeRedirectUrl("不推荐使用了");
response.encodeUrl("不推荐使用了");
response.encodeUrl("不推荐使用了");
6.String(s.getBytes("iso8859-1"),"客户端提交时的字符集"); //常用方式:尤其在获取客户端表单的参数乱码的时候
Eg:new String(request.getParameter("something").getBytes("ISO-8859-1"),"GBK") //推荐使用
7.post提交数据:处理工具org.springframework.web.filter.CharacterEncodingFilter
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>*.html</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
客户端:
0.各浏览器和系统默认采用的字符集均不同:
chrome[UTF-8]
IE[GB某系列]
windows[GB2312;UTF16LE]
chrome应用商店中有set Character Encoding插件,可以更改网页显示的字符集【针对用户】
1.form属性中:accept-charset="UTF-8" onsubmit="document.charset='utf-8';" //推荐使用
2.JS脚本:
原生JS-API:escape();
unescape();
===========
encodeURI();
encodeURIComponent();
3.自造编码轮子:
var Unicode = {
stringify : function(str) { //编码
var res = [], len = str.length;
for (var i = 0; i < len; ++i) {
res[i] = ("00" + str.charCodeAt(i).toString(16)).slice(-4);
}
return str ? "\\u" + res.join("\\u") : "";
},
parse : function(str) {//解码
str = str.replace(/\\/g, "%");
return unescape(str);
}
};
========================
小测试:
function encodeAndDecode1() {
var str1 = Unicode.stringify("我的时间123ABC"); //\u6211\u7684\u65f6\u95f4\u0031\u0032\u0033\u0041\u0042\u0043
alert(str1);
var str2 = Unicode.parse(str1); //我的时间123ABC
alert(str2);
}
function encodeAndDecode2() {
string = "我爱你12345才guai~";
var str1 = escape(string); //%u6211%u7231%u4F6012345%u624Dguai%7E
alert(str1);
var str2 = unescape(str1); //我爱你12345才guai~
alert(str2);
}
四、实际问题
===========================================================================
在Eclipse中实测有效:
实现jsp页面内的文件转码:
方法1:
使用page指令更改aim.jsp中的pageEncoding
然后,在项目目录中查看aim.jsp的编码方式:已经自动更改为pageEncoding的编码方式了
方法2:【同:更改Servlet文件编码 方式】
更改Servlet文件编码:
先在项目目录中XXXXServlet.java文件的编码方式
选中XXXXServlet所有代码【ctrl+a】
撤退【ctrl+z】
表单中文参数乱码:
step1.form中设置属性:
accept-charset="客户端字符集编码类型A" onsubmit="document.charset='客户端字符集编码类型A';"
step2:服务器端:【获取数据】
new String(request.getParameter("username").getBytes("ISO-8859-1"),"客户端字符集编码类型A"));
//ISO-8859-1是Tomcat的默认字符集编码类型
网页文本乱码:【问题很综合很复杂,暂时不予总结】
【前提:数据源来自服务器,且服务器端文本正常显示】
【假定:文件编码字符集:A;
响应的全局字符集:B【即:CharacterEncoding】
响应[全局下-文件]编码:C [即:ContentType("text/html;charset=响应[全局下-文件]编码")]
】
1.response.setContentType("text/html;charset=响应[全局下-文件]编码");
【响应[全局下-文件]编码与文件本身的编码不一致:C!=A】
如果C的字符集没有超出A的字库表范围,将出现乱码。
如果C的字符集超出了A的字库表范围,将出现500 服务器内部执行程序错误【严重情况】:
type Exception report
message Servlet execution threw an exception
description The server encountered an internal error that prevented it from fulfilling this request.
exception
javavax.servlet.ServletException: Servlet execution threw an exception root cause
java.lang.Error: Unresolved compilation problems:
The type of the expression must be an array type but it resolved to String
Syntax error on token "Invalid Character", [ expected
Servlet杈撳嚭 cannot be resolved to a variable
Syntax error, insert "]" to complete ArrayAccess
Syntax error, insert ")" to complete MethodInvocation
Syntax error, insert ";" to complete Statement
Syntax error on tokens, ( expected instead
The left-hand side of an assignment must be a variable
Syntax error, insert ")" to complete Expression
Syntax error, insert "AssignmentOperator Expression" to complete Assignment
Syntax error, insert ";" to complete Statement
servlet.testServlet.doPost(testServlet.java:54)
servlet.testServlet.doGet(testServlet.java:30)
javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
javax.servlet.http.HttpServlet.service(HttpServlet.java:723)
note The full stack trace of the root cause is available in the Apache Tomcat/6.0.48 logs.
response.setCharacterEncoding("响应全局编码");响应编码与文件本身的编码不一致,可能导致乱码