• 乱码问题解决之道


    关键词:乱码 Ajax XMLHttpRequest send JSP Java JavaScript JScript UTF-8 GB2312 UNICODE

    乱码的意思就是混乱的编码,也就是编码错误导致的问题,我们可以把编码划分成以下三个环节:

    1) 发送方对信息编码

    2) 发送编码后的信息给接收方

    3) 接手方采用什么编码分析接收到的信息

    (此处发送方和接收方应为广义的意义:B/S或C/S结构中,发送方可以是服务端或客户端,相应接收方就是客户端或服务端。当通过文件交换信息时,发送方是存储程序,接收方则是读取程序。)

    出现乱码问题肯定是至少其中一个环节出现了问题,因此乱码问题解决之道就是从上面三个环节找原因,具体而言可以问下面三个问题:

    a.       发送方的编码方式是什么

    b.       发送方把编码方式告知接收方了吗

    c.       接收方采用的编码方式是否正确

    只要能清楚的回答这三个问题,乱码问题自然就迎刃而解,这就是乱码问题解决之道。

    下面就具体的例子进一步阐述:

    例子一:JSP页面显示时的中文乱码问题,文件如下:

    <html>

    <%@page contentType=”text/html”%>

    <%=”你好!”%>

    </html>

    大部分文章对此都说把contentType增加charset=gb2312,那么果真如此吗?

    遵循乱码问题解决之道,可以有3个问题:

    a.       编辑这个文件的程序采用什么编码方式把文本存储到文件

    b.       编辑程序如何通知文件读取程序

    c.       文件读取程序采用什么编码打开

    对照着理解,我们可以看出增加charset=gb2312潜在的三层意思:第一是认为文件肯定是gb2312编码存储的;第二是文件读取程序被通知文件采用的gb2312编码存储;第三是文件读取程序将采用gb2312编码打开。看出问题了吧?

    认为文件肯定是gb2312编码存储的就犯了错误,如果有人不是以gb2312存储的,而是采用其它编码,并且和gb2312不兼容的话,那么加上charset=gb2312也没用,仍是乱码。弄清楚是什么编码再写charset才是真正解决方案,而不是简单的加上charset=gb2312

    例子二:采用Ajax时,服务端收到的是乱码

    在JavaScript代码中:

          alert(postString);          // 测试用

          ajax.send(postString);

    其中postString是中文字符串,如“高兴”,ajax则是XMLHttpRequest实例(非IE),或ActiveXObject("Msxml2.XMLHTTP")的实例(IE)。

    通过第一行的alert可以发现postString在send之前还能正常显示,但服务端

          String str=request.getParameter(“name”);

    得到的str却是乱码。

    遵循乱码问题解决之道,可以有3个问题:

    a.       ajax.send对postString是否编码了?编码方式是什么?

    b.       ajax通知服务端编码方式了吗?

    c.       服务端是采用什么编码方式读取数据的?

    第二个问题比较好回答,因为编码方式是通过Content-type中的charset传递的,在服务端代码中增加:

           System.out.println("Coding: " + request.getCharacterEncoding());

    即可,经过打印,可以看到charset是gb2312,那么ajax.send果真是采用gb2312编码吗?

    由于无法跟踪到ajax.send内部,因此只好从服务端想办法,在上面的服务端代码后面加上:

        for (i=0; i < str.length(); i++) {

           ch = str.charAt(i);

           System.out.print(ch);

           System.out.print(Integer.toBinaryString(ch));

           System.out.print(' ');

        }

    把接收到的字符串以二进制显示出来,需要注意的是Java字符串是以UNICODE码形式存储的,因此此时打印出的是UNICODE二进制编码。经过调试,发现ajax发送的“书”字在服务端打印出来是“涔”,UNICODE码是“110110110010100”,这说明ajax.send并不是以gb2312编码发送数据的,否则在服务端根据gb2312读取的是“书”,UNICODE码是“100111001100110”。

    等等,前面描述还有点问题J,里面还有个假设就是ajax发送的postString也是以UNICODE码存储的,然后通过send编码后发送出去。还好,这个假设是成立的J。开始我总想着postString是以gb2312存储的,结果费了很大劲。

    既然ajax.send不是gb2312编码,那么就另换一种,把charset改成UTF-8,这次服务端打印出来正确的“书”,也打印出它的UNICODE码。这说明ajax.send是以UTF-8编码的。第一个问题终于得到回答。(在网上搜了半天,没有看到ajax.send关于采用UTF-8编码的官方文档,因此尝试了好多次。如果一开始知道,就不用费周折了)

    通过charset=UTF-8,服务端也知道是UTF-8编码,从而能正确解析。第三个问题

    总结一下:

    l       Ajax乱码问题的关键原因是send()函数默认采用了UTF-8对待发送字符串编码。

    l       JavaSscript和Java字符串中存储的都是UNICODE码

    l       该例子的乱码问题与GB2312没有关系,把charset设置为GB2312不能解决问题

    l       解决问题方式是服务端采用UTF-8编码读取send发来的数据,需要设置charset=UTF-8

    l       期待send函数支持多种编码方式吧J

    (以上JavaScript包括JScript)

    例子三:表单提交后服务端得到乱码

    <form action=”proc.jsp” method=”post”>

       <input type=”text” name=”instr” value=””>

       <input type=”submit” value=”提交”>

    </form>

    在instr中输入中文,发送到服务端proc.jsp得到乱码,proc.jsp代码

        str = request.getParameter("instr");

    遵循乱码问题解决之道,可以有3个问题:

    a.       表单提交的instr是否编码了?编码方式是什么?

    b.       表单提交的数据包中明确编码方式了吗?

    c.       服务端是采用什么编码方式读取数据的?

    第一个问题自己清楚,例如我是以gb2312保存文件的,因此编码方式是gb2312

    通过在服务端加上以下语句:

           System.out.println("Coding: " + request.getCharacterEncoding());

    可以回答问题b,结果是null,这说明第二个环节出了问题。解决办法就是让表单提交的数据包中明确编码方式,也就是在form属性中增加:

           accept-charset = “gb

    不过IE6.0以前版本(7不知道,没试过)不支持这个属性,因此只能采用跳过第二个环节,直接为服务端指定编码方式,这也是网上普遍给出的解决方案,在getParameter()之前加上:

           request.setCharacterEncoding("gb2312");

    当然也可以采用

    str = new String(request.getParameter("instr").getBytes("iso-8859-1"), "gb2312");

    即先按iso-8859-1编码读出,此时存储的是gb2312编码值,然后利用Java的String构造函数以gb2312解码字符串为UNICODE字符串存储,结果一样,不过稍显烦琐。

    最后强调一句,网上很多人建议把网页文件采用UTF-8编码存储,其实没有必要,仍旧可以采用GB2312存储,在出现乱码问题时(或之前)问问上面的三个问题即可。

  • 相关阅读:
    FPGA时序约束的几种方法
    使用NiosII代替SignalTap来监测FPGA内部数据
    Modelsim的使用
    Modelsim+Debussy
    ChipScope用法总结
    QuartusII增量编译的个人学习
    quartus II .qsf文件(zz)
    RAM与Nand/Nor flash之间的区别 (转)
    黑金资料AX301_A的Quartus工程建立、编译及引脚分配、程序下载
    关于sg90舵机的,要知道!要注意!
  • 原文地址:https://www.cnblogs.com/elleniou/p/3177870.html
Copyright © 2020-2023  润新知