`

中文乱码的那些事儿(二)

 
阅读更多

中文乱码的那些事儿(一)中基本没提及任何乱码的事情,被骂标题挡了,本篇主要侧重乱码问题的排查过程,讨论一下处理这类问题的思路。

一次典型的B/S结构的Web请求过程大概是下面这个样子的:

浏览器发起request(第一次Encode,将待发送的数据通过某种字符编码编码为字节流) -------> 服务器接收请求(第一次Decode,如果此时使用了和浏览器端不一致的字符编码进行解码,则有可能在这一时刻产生乱码)-------> 服务器内部业务逻辑处理(这里如果涉及DB交互,则这里还有一次编码解码过程,不过以下讨论忽略这种情况,简化问题,分析的思路是一致的) -------> 服务器发送response给浏览器(第二次Encode,涉及到字符编码) -------> 浏览器接受到HttpResponse进行解码页面渲染(第二次Decode,再一次涉及字符编码)

从这个简化的过程可以看出,只要上面任何一对编码解码的字符编码不一致,都有可能造成乱码(这里说有可能是因为如果你刚好使用了一个可以完全兼容编码字符集的字符集进行解码,那么你可能很幸运的没遇到乱码问题,前提条件是编码字符集能够涵盖你发送的所以字符,不会在编码那一刻造成信息丢失)。

下面分别来看一下这几个环节的细节:

  • 第一次Encode:浏览器发出的常用请求,主要是POST和GET两种。对于这两种请求,如果是通过form形式提交的,那么字符编码的最高优先级是遵守form中accept-charset属性的值。但在实际网页中,很少有人使用这个属性,事实上,通常情况下,你也没有理由单独为文本形式提交的form规定一个单独的字符编码进行编码。在这个属性不存在的情况下,HTTP的Response的Header中的Content-Type会作为网页提交的默认字符编码;如果这个也不存在,那么浏览器会选择网页中head标签中的
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    作为字符编码。如果这个也找不到呢?那只能说明这个网页是在太尼玛不规范了,浏览器也不忍了,直接自己决定,通常这种情况会使用默认的操作系统字符集。对于非form的普通GET请求,基本也是遵循这个优先级套路的。但是,上面主要是个理论依据,在乱码问题排查时,最好的方式还是通过实践确认这个第一步编码使用的到底是啥编码,这个至关重要,会作为后续分析的一个重要依据。在Firefox和Chrome中,想获得这个信息太容易了,只要你在提交请求之前,打开相应的监控插件就可以了。如果你非得使用比较老版本的IE进行调试,那开个Fiddler也行的。
  • 第一次Decode:这次Decode发生在字节流已经成功发送到Server端(好吧,这里我们再次忽略了Http服务器,比如Apache,插手解码的过程,因为这个也确实不常见,通常他会直接做一个反向代理的转发到他后面的Web服务器)。这时,Web服务器需要进行解码了。注意,这里可能产生乱码了。这时你会惊呼:“尼玛,我明明用UTF-8编码的,为啥这里用UTF-8进行解码出来一坨乱码!”。如果你在上面一步确实通过实践证明了浏览器在发送之前使用的是UTF-8进行了编码,并且这一步是网络传输之后的第一次解码环节,那么问题就找到了,你使用了非UTF-8解码。于是你兴高采烈的在你使用Request.getParameter("XXX")之前,加入了一句Request.setCharacterEncoding("UTF-8"),然后重新编译代码等待见证奇迹。然后,我和我的小伙伴们都惊呆了,因为乱码还尼玛依旧是乱码。为啥?为啥设置的编码没生效?因为Request的解码动作是在第一次调用它的getParameter方法时发生的,且在一次Request的周期中,只发生这一次(想想也合理,如果是你实现这个方法,也不可能每次都去重新Decode一遍字节数组吧)!这点很重要,了解了这点,一种合理的解释就是,你手动触发的getParameter("XXX")并不是第一次这个方法的调用。至于是谁更早的调用了这个方法,这个通常跟你使用Web框架有关系。通常在框架级别,出于安全、适配等方面的考虑,很有可能在你的业务代码之前已经把你Request中的paramter已经先轮了一遍了。那你要做的就是想尽办法你上面的那句设置编码的Code放到最近前面就好了。一种可行的方案是你编写一个Servlet的Filter专门干编码设置这件事情,并且把它放置到所有Filter的最前面(通过配置filter-mapping标签在web.xml中的顺序来实现)。事实上,Spring框架中提供的org.springframework.web.filter.CharacterEncodingFilter就干了这么一件事。以上这个过程你可以通过IDE提供的Debug或者调试Log等手段加以验证。
  • 第二次Encode:话说上面两步都没问题,那你就得确定在你Response回去的时候,使用的字符编码是不是你所期望的了。比较保险的做法通常是在你对Response有任何写操作之前,设置好他的编码。也就是在最开始就设置好Response的字符编码,这个在Servlet的API中,可以对应到Response.setCharacterEncoding("XXX")。
  • 第二次Decode:回到这一步,已经到页面展示的最后一公里了。如果通过上面步步为营的排查,确保每一步都没问题,到这一步还是有乱码,那八成就是浏览器用了错误的编码解析了网络回传回来的字节流。那怎么排查?单独这一步其实好验证,因为绝大部分浏览器都支持让你手动选择使用神马字符编码解码。最快的验证方式就是把常用的那几个字符编码快速验证一下,通常你可以通过这种方式找到正确的解码字符集。剩下的就是看看浏览器为啥没有按照正确的字符集进行解码了。其实如果你正确的完成了上一步所说的所有步骤的话,在Server端返回的HTTP的Header中就会明确的有Content-Type这个属性。所以这一步其实差不多和上一步是一个互相验证的过程。

好了,当你已经完成上面提到的几步的排查过程,可能你的乱码问题就解决了。当然也可能没有。上面毕竟仅仅描述了一种比较典型的Web交互过程,实际的交互过程完全有可能更为复杂,完全有可能进行更多次的编码解码。但是上面列出的排查问题的过程还是具有普世意义的:找到你的字符在整个过程中究竟有多少地方进行了编码和解码,然后从第一个编码的地方开始,通过各种工具或者Debug的手段开始确认,找到最先出现乱码的地方,然后解决。然后再实验问题是否得到解决。

分享到:
评论

相关推荐

    使用ODBC中文乱码问题.docx

    ODBC中文乱码问题解决方案 在使用ODBC对数据库进行中文字符串插入时,经常会遇到中文字符串显示乱码的问题。本文将通过对该问题的分析和解决方案,帮助读者更好地理解ODBC中文乱码问题的成因和解决方法。 一、问题...

    c#汉字乱码处理

    在C#编程中,处理汉字乱码问题是一个常见的需求,尤其是在读取或写入文本文件时。当在C#控制台应用中遇到汉字输出乱码的情况,这通常是因为编码不匹配所导致的。编码是字符集与二进制数据之间的转换规则,不同的系统...

    Lua文件反编译汉字乱码处理

    然而,当处理含有汉字的Lua文件时,反编译过程中可能会出现汉字乱码的问题,这主要与字符编码不匹配有关。本文将详细介绍如何在C#环境下,特别是使用Visual Studio 2013时,解决Lua文件反编译后的汉字乱码问题。 ...

    彻底解决中文乱码的问题

    在IT行业中,尤其是在Java编程领域,中文乱码问题是一个常见的挑战。这主要涉及到字符编码的处理,涉及到Unicode、GBK、UTF-8等不同编码格式之间的转换和一致性问题。本篇文章将深入探讨这个问题,并提供一种彻底...

    Linux系统中文乱码解决完整方案

    Linux系统中文乱码解决完整方案 本文档旨在解决 Linux 系统中文乱码问题,提供了一个完整的解决方案。该问题是由于 Linux 和 Windows 系统下所用户的字符集不同,Linux 系统使用的是 Unicode 字符集,而 Windows ...

    在eclipse中中文汉字乱码的解决方案

    Eclipse 中中文汉字乱码的解决方案 Eclipse 是一个功能强大且广泛使用的集成开发环境(IDE),但是在使用过程中,用户可能会遇到中文汉字乱码的问题。本文将为大家分享解决 Eclipse 中中文汉字乱码的方案,以便大家...

    乱码解决 乱码解决 乱码解决 乱码解决 乱码解决

    二、乱码的解决方法 1. **确定编码格式**:首先,你需要确定原始文件的正确编码格式。可以使用诸如Notepad++、HexEdit等工具来查看文件的字节序列,从而推测其可能的编码。 2. **编码转换**:一旦确定了正确的编码...

    express中文乱码解决

    #### 二、解决中文乱码的具体步骤 ##### 1. 设置HTTP响应头 在Express应用中,可以通过设置HTTP响应头来指定字符集为UTF-8,确保前后端数据传输的一致性。示例代码如下: ```javascript app.use((req, res, next)...

    ZXing 2.1版GBK中文乱码解决办法

    ZXing 2.1版GBK中文乱码解决办法: zxing中扫瞄二维码图片,如果包含Gbk中文,乱码解决办法是修改DecodedBitStreamParser.h文件,在里面加入GBK的判断。 在2.1版本中,解码的定义不在这个类中了,挪到了...

    soapUI输入中文显示为乱码,响应报文中文乱码问题解决方法.txt

    soapUI输入中文显示为乱码 响应报文中文乱码问题解决方法

    C# 将中文乱码转换成中文

    本文将深入探讨如何使用C#语言解决中文乱码问题,将乱码文本正确转换为可读的中文。 ### 核心知识点:字符编码与转换 #### 1. 字符编码概念 字符编码是计算机用于存储、传输和显示文字的一套规则,它将字符映射到...

    中文乱码问题分析 自己总结的

    中文乱码问题分析 中文乱码问题是 Java 和 JSP 开发中的一种常见问题,主要是由于 Java 和 JSP 源文件的保存方式是基于字节流的,而编译成 class 文件过程中,使用的编码方式与源文件的编码不一致所致。在 Java ...

    Navicat for MySql 导入EXCEL中文乱码问题解决

    ### Navicat for MySQL 导入Excel中文乱码问题解决 #### 一、问题背景 在使用Navicat for MySQL工具进行数据导入时,经常会出现中文乱码的问题,尤其是在处理Excel文件时更为常见。这种现象不仅影响数据的正确性,...

    plsql乱码解决办法

    二是查询结果集中文乱码。 问题分析 当我们安装 PL/SQL Developer 后,默认情况下,系统的字符集设置可能不是我们所期望的中文字符集。这将导致在查询数据时出现中文乱码的问题。 解决办法 要解决 PL/SQL 乱码...

    csv文件中文会乱码工具

    excel打开csv文件中文乱码问题,将乱码文件拖到此工具就可完成转码,正常显示中文。

    dbf解决中文乱码

    在处理包含中文字符的DBF文件时,可能会遇到中文乱码的问题,这通常与编码设置不匹配有关。以下是一些关于解决DBF文件中文乱码的详细知识: 1. **编码问题**:DBF文件的字符编码可能是GBK、GB2312或BIG5等,而你的...

    FORM表单中文乱码问题分析与解决

    FORM表单中文乱码问题分析与解决 在 Web 开发中,中文乱码问题是一个常见的问题,尤其是在FORM表单传递参数时。这个问题的根本原因是对中文的编码与解码方式不一致。我们可以理解为对中文的加密与解密的密钥不一致...

Global site tag (gtag.js) - Google Analytics