`
txf2004
  • 浏览: 6876649 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

中文编码问题全面分析

阅读更多


  基于web的应用开发都会涉及到编码问题,特别是中文编码,一直是开发人员常见问题之一,也最为初学者所困扰。我们知道计算机最初是按英语单字节字符设计的,现在很多软件及系统仍然默认使用ISO8859-1编码来表示。因此,有的时候处理中文字符就会出现乱码的现象。出现乱码不只是简单的由某个软件所造成的,很可能与系统或相关软件有关联影响。

  在web软件开发过程中,我们将涉及到四个可能会导致字符编码问题的方面,分别为浏览器、中间件(WEB服务器)、数据库、操作系统。在这四个方面,都有影响字符编码的因素存在。每个方面都有自己默认支持的字符编码,如果这四方面的编码是统一的一种字符集,一定不会出现乱码问题。出问了乱码,一定是其中某部分有不同的字符集编码存在。目前解决此类的问题的方法也是多种多样,本文提到的也是其中的一种,也许别人有更好的方法欢迎大家一起进行探讨。
  操作系统本地编码与你所选择安装的系统版本有关,如果你是简体windows,就是GB编码,如果你是繁体windows,就是BIG5编码。所以我们在不同的操作系统上创建一个源码文件,由于系统的不同就会存储成不同编码格式。这个时候当采用另外一种编码格式的操作系统来读取这个源码文件的时候,内容就会是乱码的。同理,采用浏览器解析的时候也是一样的。如:你的源码文件是在BIG5编码的操作系统下创建的,而浏览器或是WEB服务器(apache等)采用的是GB2312编码的,这个时候所显示的内容也一定是乱码的。知道乱码的原因了,我们就可以有效的解决这个问题。
  要想彻底解决这个问题,就需要我们决定采用统一的编码。对于当前众多的字符集编码,是UNICODE、ISO8859_1 、GBK还是UTF-8。
  UNICODE编码不兼容ISO8859-1编码,而且容易占用更多的空间。因为对于英文字母,UNICODE也需要两个字节来表示,不便于传输和存储。而UTF-8编码兼容ISO8859-1编码,同时也可以用来表示所有语言的字符。UTF-8编码是不定长编码,每一个字符的长度从1-6个字节不等,并且自带简单的校验功能。在UTF-8编码中通常英文字母都是用一个字节表示,而汉字使用三个字节。虽然说UTF-8编码可以使用更少的空间,但只是相对于UNICODE编码来言,如果只是处理汉字,使用GB2312/GBK才是最节省的。WEB应用,网页中会包含大量的英文字符,由于UTF-8编码对ISO8859-1编码兼容,它是一种兼容所有语言的编码方式 ,所以建议采用UTF-8编码为最佳选择。如果决定采用UTF-8编码,做为统一编码。从开发环境到数据库、中间件、系统平台都需要进行统一。
  开发基于WEB的应用,应该了解到所采用的开发语言内部运算中,对字符操作的编码过程。如java语言,在内部将涉及到的所有字符串都会被转化为UTF-8编码来进行运算。
  字符串在被开发语言转化之前,字符串的字符集是什么? 很多开发语言总是根据操作系统的默认编码字符集来决定字符串的初始编码,而且编译或解释系统的输入和输出的都是采取操作系统的默认编码。问题往往就出在输入与输出的地方。而输入与输出部分涉及到WEB服务器、浏览器、数据库等。出现乱码的时候要分析清楚乱码出自哪儿个部分,是输入部分,还是输出部分,确定问题很是困难。下面分别从几个部分来说这个问题。
  
一,开发环境及浏览器部分
  将开发环境的默认字符集设置为UTF-8编码,很多开发工具都可以自定义设置,如Eclipse可以设置全局默认字符集编码也可以在项目属性中设置项目自身采用的字符集编码。
这样在创建源码文件的时候,文件本身就会采用UTF-8编码格式进行存储。
  在WEB开发过程中,各类源代码文件都是文本文件格式的。如最常见的HTML文件,它就是以文本文件格式存储的。这些文件如果是在系统内直接建立的文件,它的编码就是系统的默认编码。如果是在开发工具中创建的文件,一般情况上都是由开发工具的默认编码设置来决定的。而在HTML文件里,还要使用HTML语法,指定了该文件内容所使用的编码(如< meta http-equiv="content-type" content="text/html; charset=UTF-8">)。如果HTML文件内容没有指定编码,则浏览器自动识别文件的编码。如果HTML内容指定了编码,则浏览器使用HTML指定的编码来显示内容。通常情况下,HTML文件指定的charset和HTML文件自身的编码是一致的,但也有不一致的情况,如果不一致,就会导致网页乱码(此处乱码,只和文本文件编码有关,和数据库无关。)使用专门的网页编辑工具(比如Dreamwave),会自动根据网页中的charset值来编码文件。
二,程序文件部分
  页面文件主要包括html文件及脚本文件及其它由开发语言直接输出内容的文件。对于html文件的编码问题,前面讲过了,这里不再重复。开发语言输出的文件,有的是需要进行编码设置的,如jsp开发的时候,需要在jsp文件的头部对字符集进行声明。
如:<%@ page contentType="text/html;charset= utf-8" %>
在Jsp的html代码中,声明UTF-8编码:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
这样只要保证了这个页面内容的编码与文件本身编码一至就会避免与文件相关的乱码。再有乱码就可能是数据在传递过程中编码不同导致的。对于数据传递过程中出现乱码,一般采用对数据时行过滤来处理,数据统一经过某个程序进行编码处理来解决这个问题。
  例如在java的web应用中采用过滤器的方式进行编码处理,将所有来自浏览器的请求(request)转换为UTF-8,因为浏览器发过来的请求包根据浏览器所在的操作系统编码,可能是各种形式编码。网上这方面的源代码很多,下面就是编码过滤器的源代码。需要配置web.xml 激活该Filter。

SetCharacterEncodingFilter源文件

packageorg.kyle.web.sample;
importjava.io.IOException;
importjavax.servlet.Filter;
importjavax.servlet.FilterChain;
importjavax.servlet.FilterConfig;
importjavax.servlet.ServletException;
importjavax.servlet.ServletRequest;
importjavax.servlet.ServletResponse;
importjavax.servlet.UnavailableException;
publicclassSetCharacterEncodingFilterimplementsFilter
...{
/***//**
*Thedefaultcharacterencodingtosetforrequeststhatpassthrough
*thisfilter.
*/

protectedStringencoding=null;

/***//**
*Thefilterconfigurationobjectweareassociatedwith.Ifthisvalue
*isnull,thisfilterinstanceisnotcurrentlyconfigured.
*/

protectedFilterConfigfilterConfig=null;


/***//**
*Shouldacharacterencodingspecifiedbytheclientbeignored?
*/

protectedbooleanignore=true;

/***//**
*Takethisfilteroutofservice.
*/

publicvoiddestroy()
...{
this.encoding=null;
this.filterConfig=null;
}


/***//**
*Selectandset(ifspecified)thecharacterencodingtobeusedto
*interpretrequestparametersforthisrequest.
*
*
@paramrequestTheservletrequestweareprocessing
*
@paramresultTheservletresponsewearecreating
*
@paramchainThefilterchainweareprocessing
*
*
@exceptionIOExceptionifaninput/outputerroroccurs
*
@exceptionServletExceptionifaservleterroroccurs
*/

publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,
FilterChainchain)
throwsIOException,ServletException
...{

//Conditionallyselectandsetthecharacterencodingtobeused
if(ignore||(request.getCharacterEncoding()==null))
...{
Stringencoding
=selectEncoding(request);
if(encoding!=null)
request.setCharacterEncoding(encoding);
}


//Passcontrolontothenextfilter
chain.doFilter(request,response);
}



/***//**
*Placethisfilterintoservice.
*
*
@paramfilterConfigThefilterconfigurationobject
*
*encoding
*UTF-8
*
*/

publicvoidinit(FilterConfigfilterConfig)throwsServletException
...{
this.filterConfig=filterConfig;
this.encoding=filterConfig.getInitParameter("encoding");
Stringvalue
=filterConfig.getInitParameter("ignore");
if(value==null)
this.ignore=true;
elseif(value.equalsIgnoreCase("true"))
this.ignore=true;
elseif(value.equalsIgnoreCase("yes"))
this.ignore=true;
else
this.ignore=false;
}


/***//**
*Selectanappropriatecharacterencodingtobeused,basedonthe
*characteristicsofthecurrentrequestand/orfilterinitialization
*parameters.Ifnocharacterencodingshouldbeset,return
*null.
*


*Thedefaultimplementationunconditionallyreturnsthevalueconfigured
*bytheencodinginitializationparameterforthis
*filter.
*
*
@paramrequestTheservletrequestweareprocessing
*/

protectedStringselectEncoding(ServletRequestrequest)
...{
return(this.encoding);
}

}



*Thedefaultimplementationunconditionallyreturnsthevalueconfigured
*bytheencodinginitializationparameterforthis
*filter.
*
*@paramrequestTheservletrequestweareprocessing
*/
protectedStringselectEncoding(ServletRequestrequest)
...{
return(this.encoding);
}

}
在web.xml文件中加注册这个过滤器

<filter>
<filter-name>setCharacterEncodingFilter</filter-name>
<display-name>setCharacterEncodingFilter</display-name>
<description>setCharacterEncodingFilter</description>
<filter-class>org.kyle.web.sample.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
这样就可以避免数据在传递过程中因编码不同造成乱码问题。
三,中间件(WEB服务器)
设置WEB服务器的默认编码为UTF-8,与文件编码及文件内容声明编码相同,这样保证了WEB服务器在解释文件的时候不出现乱码问题。
如:
Apache服务器可以在它的httpd.conf配置文件中增加AddDefaultCharset utf-8设置。
Weblogic服务器可以在WEB-INF下的web.xml文件中加入以下设置就可以解决这个问题。

<context-param>
<param-name>weblogic.httpd.inputCharset./*</param-name>
<param-value>utf-8</param-value>
</context-param>
其它的WEB服务器在其配置文件中都提供设置默认编码的选项,这里不再一一列举。

四,数据库
  经过上面的处理,会发现你的web程序运转起来后,程序已没有了乱码问题。但是在增加记录的时候有的时候也有乱码出现。这是因为你的数据库编码与你通过程序输入的数据编码不同导致的。这需要设置数据库的编码。每种数据库都有直接修改数据库默认编码的配置项。如mysql数据库,可以在它的my.cnf(win:my.ini|unix/linux:my.cnf)配置文件中设置:
[mysql]
default-character-set=utf-8
但是不建议直接修改数据库的这个编码设置。如果修改了数据库的默认编码配置,就破坏了数据库原有的环境,而数据库通常情况下是多人在使用,并不是做为唯一的项目应用。
在我们的程序里可以采用在连接数据库的时候指定编码来解决这个问题。
通过java程序操作数据库的时候,连接数据库的URL可以写成:
useUnicode=true;characterEncoding=utf-8
如连接mysql数据库:
jdbc:mysql://localhost/test?useUnicode=true;characterEncoding=utf-8
通过PHP程序操作数据库的时候,可以先执行mysql_query(“set names xxxx”);其中xxxx是你网页的编码(charset=xxxx),如果网页中charset=utf8,则xxxx=utf8,如果网页中 charset=gb2312,则xxxx=gb2312。
  通过上面几部分的处理,我们可以彻底解决操作系统、开发环境、web服务器、数据库四部分在整个WEB应用中产生乱码的问题。当然很多时候我们没办法将这四部分调整为相同的编码。如你采用的是别人的web服务器,没有权力修改web服务器的默认编码,那么只有在你的程序中对于需要编码的地方进行转换处理,转换成web服务器相同的编码即可。
分享到:
评论

相关推荐

    关于C++程序的编码问题

    我们传统的程序基本都只在Windows或只在Linux下运行,Windows程序使用简体中文GB18030编码,Linux程序则只使用英文,多年以来这些程序运行起来都没有问题。  近年来,随着程序的组件化,部分代码特别是公用组件都...

    java 编码 UTF-8、ISO-8859-1、GBK

    如果在编程中遇到不能正确显示中文时 要先弄清楚以上几项所使用的字体编码 再分析找出原因 即可解决问题 "&gt;ava支持UTF 8 ISO 8859 1 GBK等各种字体编码 可笔者发现Java中字体编码的问题仍难倒了不少程序员 网上虽然...

    深入分析Java Web技术内幕高清PDF版.zip

    其次深入介绍Java技术,包括I/O技术、中文编码问题、Javac编译原理、class文件结构解析、ClassLoader工作机制及JVM的内存管理等。最后介绍Java服务端技术,主要包括Servlet、Session与Cookie、Tomcat与Jetty服务器、...

    FireBird存储过程

    对FireBird存储过程的全面分析,对于学习firebird的同学有借鉴价值。

    深入分析Java Web技术内幕 修订版.pdf

    其次深入介绍了Java 技术,包括I/O 技术、中文编码问题、Javac 编译原理、class 文件结构解析、ClassLoader 工作机制及JVM 的内存管理等。最后介绍了Java 服务端技术,主要包括Servlet、Session 与Cookie、Tomcat 与...

    VOS3000 v2.1.6.0客户端 官方中文安装版

    方便的问题定位方式,图形化显示呼叫分析,注册分析 能够对硬件,软件,业务进行全面的监控 全面的第三方接口 负载均衡和过负荷保护机制 网关群组,预设网关费率 语音编码强制选定 实时软交换平台控制 全面...

    数据结构与算法分析_Java语言描述(第2版)

    《数据结构与算法分析:Java语言描述(第2版)》把算法分析与最有效率的Java程序的开发有机地结合起来,深入分析每种算法,内容全面、缜密严格,并细致讲解精心构造程序的方法。 内容截图 目录: 译者序 前言 ...

    ABAP∕4 开发宝典中文版

    · 向新的ABAP/4程序员提供从基本语言组件到复杂报表和事务编码的全面指导 · 向资深ABAP/4程序员提供解决特殊问题的参考方案 为满足这些需求,特提供一个整体概述并本宝典分成三个部分,循序渐进,逐步深入 · ABAP...

    数据结构与算法分析_Java语言描述(第2版)]

    中文名: 数据结构与算法分析_Java语言描述(第2版)作者: 韦斯译者: 冯舜玺资源格式: PDF版本: 扫描版出版社: 机械工业出版社书号: ISBN:9787111231837发行时间: 2009年01月01日地区: 大陆语言: 简体中文简介: 内容...

    深入分析Java Web技术内幕 修订版

    其次深入介绍了Java 技术,包括I/O 技术、中文编码问题、Javac 编译原理、class 文件结构解析、ClassLoader 工作机制及JVM 的内存管理等。最后介绍了Java 服务端技术,主要包括Servlet、Session 与Cookie、Tomcat 与...

    数据结构与算法分析 Java语言描述第2版

    中文名: 数据结构与算法分析_Java语言描述(第2版)作者: 韦斯译者: 冯舜玺图书分类: 软件资源格式: PDF版本: 扫描版出版社: 机械工业出版社书号: ISBN:9787111231837发行时间: 2009年01月01日地区: 大陆语言: 简体...

    abap4开发宝典中文版

    · 向新的ABAP/4程序员提供从基本语言组件到复杂报表和事务编码的全面指导 · 向资深ABAP/4程序员提供解决特殊问题的参考方案 为满足这些需求,特提供一个整体概述并本宝典分成三个部分,循序渐进,逐步深入 · ...

    ABAP/4开发宝典中文版

    · 向新的ABAP/4程序员提供从基本语言组件到复杂报表和事务编码的全面指导 · 向资深ABAP/4程序员提供解决特殊问题的参考方案 为满足这些需求,特提供一个整体概述并本宝典分成三个部分,循序渐进,逐步深入 · ABAP...

    算法导论中文版

    本书将严谨性和全面性融为一体,深入讨论各类算法,并着力使这些算法的设计和分析能为各个层次的读者接受。全书各章自成体系,可以作为独立的学习单元;算法以英语和伪代码的形式描述,具备初步程序设计经验的人就能...

    代码大全中文版

    创建活动未受到应有的重视 在一段时期内,软件开发与编码被当作是一回事,但随着软件开发周期中的其它活动被认识,这一领域内的主要努力全部集中到了项目管理、需求分析、设计和测试等方面,创建活动成了...

    黄易输入法v11.10

    经过深思熟虑后采用部首+笔画的汉字编码技术,同样是明智的,因为部首与五笔画是国人最熟悉的汉字部件,几乎不用学就会用。如遇个别字不会取部首,可通过菜单项"编码查询"或"网上查字"得到解决。只用200多个部首就将...

    全功能文件重命名(功能强大!)

    ■ 高级文件名变更:包括正则表达式、Pascal和Python脚本更名、文件名编辑器、汉字转拼音、文件名编码与解码、数字与汉字的转换、文件名编码格式转换、文件名内码转换、文件名加密解密等重磅功能 ■ 扩展名变更:...

    《算法》中文版,Robert Sedgewick,塞奇威克

    编辑推荐  Sedgewick之巨著,与高德纳TAOCP一脉相承  几十年多次修订,经久不衰的畅销书  涵盖所有程序员必须掌握的50种算法 内容简介 ...5.5.5 游程编码 5.5.6 霍夫曼压缩 第6章 背景 索引

    ABAP∕4 用户中文指南

    · 向新的ABAP/4程序员提供从基本语言组件到复杂报表和事务编码的全面指导 · 向资深ABAP/4程序员提供解决特殊问题的参考方案 为满足这些需求,特提供一个整体概述并本指南分成三个部分,循序渐进,逐步深入 · ABAP...

    ABAP中文帮助 用户指南 PDF

    向新的ABAP/4程序员提供从基本语言组件到复杂报表和事务编码的全面指导 向资深ABAP/4程序员提供解决特殊问题的参考方案 为满足这些需求,特提供一个整体概述并将本指南分成三个部分,循序渐进,逐步深入: ABAP/4...

Global site tag (gtag.js) - Google Analytics