编码与乱码小结

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("响应全局编码");响应编码与文件本身的编码不一致,可能导致乱码

赞赏-支付宝二维码
本文作者千千寰宇
本文链接 https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:若本文对您有帮助,可点击右下角推荐一下。您的鼓励、【赞赏】(左侧赞赏支付码)是博主技术写作的重要动力!
原文地址:https://www.cnblogs.com/johnnyzen/p/7017857.html