谈谈WEB开发中的苦大难字符集问题

开发 前端
记得刚做javaweb开发的时候被这个编码问题搞得晕头转向,经常稀里糊涂的编码正常了一会编码又乱了。那个时候迫于项目进度大多都是知其然不知其所以然。后来有时间就把整个体系搞了个遍,终于摸通了来龙去脉。

记得刚做javaweb开发的时候被这个编码问题搞得晕头转向,经常稀里糊涂的编码正常了一会编码又乱了。那个时候迫于项目进度大多都是知其然不知其所以然。后来有时间就把整个体系搞了个遍,终于摸通了来龙去脉。

在C++的CGI开发时大家喜欢用latin,这个属于字节方式的编码格式,存储mysql节约空间,而C++也是比较容易控制到byte级别的语言。所以经过框架封装基本也问题不大。

在Java语言中,要涉及修改编码问题的地方还真多。一个地方没有设好就会乱码满天飞。大概总结包括以下这几部分:浏览器、服务器、数据库、操作系统。

浏览器:

如果使用模板语言,html需要设置显示的字符集。这个适用于浏览器判断什么编码显示。

  1. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 

扩展,浏览器识别编码的顺序:
1.如果HTTP头部申明了charset,则会使用HTTP头部的,
2.让HTTP头部没有设置,则会去解析meta标签的,
3.如果meta也没有的话,浏览器会根据是否设置了auto detect来进行编码识别,
4.否则会使用本地UI的字符编码。

服务器:
对于JSP等动态语言,需要在jsp头部设置编码格式,J2EE服务器解析这个JSP的时候才会把整个页面编码为UTF-8输出,不然就按照系统默认编码格式ISO-8859-1输出了。JSP设置格式如下:

  1. <%@ page language"java" contentType = "text/html; charset=UTF-8" 
  2.       pageEncoding ="UTF-8" %> 

大家都知道,JSP对应的就是servlet。servlet的编码对应如下设置:

  1. public void service(HttpServletRequest request, HttpServletResponse response) 
  2. throws ServletException,IOException{ 
  3. response.setContentType("text/html;charset=utf-8"); 

还有不要漏掉大家常用的spring工具类,编码转换filter,很实用。在你用struts、spring mvc时这个过滤器帮你转换没有设置的编码过滤。如下设置:

  1. <filter> 
  2.             <filter-name> Set Character Encoding</filter-name> 
  3.             <filter-class> 
  4.                  org.springframework.web.filter.CharacterEncodingFilter 
  5.             </filter-class> 
  6.             <init-param> 
  7.                   <param-name> encoding</param-name> 
  8.                   <param-value> UTF-8</param-value> 
  9.             </init-param> 
  10.       </filter> 

万一还有乱码怎么办呢?doGet方式的参数传递肯定会有乱码问题。只需要在tomcat的监听器里设置编码字符集如下(文件一般存储在 /tomcat安装目录/conf/server.xml ):

  1. <Connector port="80" protocol="HTTP/1.1" 
  2.               connectionTimeout="20000" 
  3.               redirectPort="8443" URIEncoding="utf-8"   /> 

大家在开发的时候别忘了java文件本身也是有编码格式的。在类文件右键查看属性。

eclipse属性

 

 

如果开发时忘记更改文件的编码格式,windows默认是GBK的,后来又要一直到utf8编码的linux怎么办。文件巨多,总不能一个一个去更改吧。其实很简单,只需要在java命令的环境参数设置 -Dfile.encoding=GBK 解决。

编译java代码时,如果使用ant需要在javac里设置编译的字符集。这样打印的log输出到文件或者控制台上就不会乱码了。

  1. <javac debuglevel"source,lines" source"1.6"   encoding"utf-8"> 

maven编译时设置的字符集:

  1. < artifactId> maven-compiler-plugin </artifactId > 
  2.        < version> 2.5 </version > 
  3.                         
  4.          < configuration> 
  5.            < optimize> true </optimize > 
  6.            < showDeprecation> false </showDeprecation > 
  7.            < debuglevel> lines,source </debuglevel > 
  8.             < source> 1.6 </source > 
  9.             < target> 1.6 </target > 
  10.             < encoding> UTF-8 </encoding > 
  11.             < meminitial> 128m </meminitial >   
  12.              < maxmem> 768m </maxmem > 
  13.                         
  14.          </ configuration> 

sqlmap的sql xml,sping的xml 也是需要设置的,因为涉及到跨平台。 顶上添加:

  1. <!--?xml version="1.0" encoding="UTF-8"?--> 

数据库:
这里列出大家用的最多的Mysql字符集设置。打开mysql的配置文件( linux 一般在 /etc/my.cnf ,windows在mysql的安装目录 my.ini)。设置如下:

  1. [mysqld] 
  2. default-character-set = utf8 
  3.  
  4. [ mysql] 
  5. character_set_server = utf8 

jdbc需要设置

jdbc : mysql://192.168.0.237:3306/dzh_db?useUnicode=true&characterEncoding=UTF-8

这些都设置了一般的中文是不会有问题的。

不过最近出现了一个问题很搞怪。以前以为所有的字符只要设置好了所有数据都可以录入数据库,结果有些字符就不行,比如●■★这类型的。后来把这些字符变成字节码,居然不是三位utf8的,我擦,大汗淋漓。后来查询可以通过过滤utf8 特殊字符的方式处理。

#p#

  1. public static String Utf2String (byte buf[]) { 
  2. int len = buf.length ; 
  3. StringBuffer sb = new StringBuffer(len / 2); 
  4. for (int i = 0; i &lt; len; i++) { 
  5.  
  6. if (by2int(buf[i]) &lt;= 0x7F) 
  7. sb.append(( char ) buf[i]); 
  8. else if (by2int(buf[i]) &lt;= 0xDF &amp;&amp; by2int(buf[i]) &gt;= 0xC0) { 
  9. int bh = by2int(buf[i] &amp; 0x1F); 
  10. int bl = by2int(buf[++i] &amp; 0x3F); 
  11.  
  12. bl = by2int(bh &lt;&lt; 6 | bl); bh = by2int(bh &gt;&gt; 2); 
  13. int c = bh &lt;&lt; 8 | bl; 
  14. sb.append(( char ) c); 
  15. } else if (by2int(buf[i]) &lt;= 0xEF &amp;&amp; by2int(buf[i]) &gt;= 0xE0) { 
  16. int bh = by2int(buf[i] &amp; 0x0F); 
  17. int bl = by2int(buf[++i] &amp; 0x3F); 
  18. int bll = by2int(buf[++i] &amp; 0x3F); 
  19.  
  20. bh = by2int(bh &lt;&lt; 4 | bl &gt;&gt; 2); 
  21. bl = by2int(bl &lt;&lt; 6 | bll); 
  22.  
  23. int c = bh &lt;&lt; 8 | bl; 
  24. // 空格转换为半角 
  25. if (c == 58865) { 
  26. c = 32
  27. sb.append(( char ) c); 
  28.  
  29. return sb.toString(); 

或者把mysql的字符集改为 utf8mb4 ,记得这个只有mysql55支持哦!

  1. [mysqld] 
  2. default-character-set =utf8mb4 
  3.  
  4. [ mysql] 
  5. character_set_server = utf8mb4 

操作系统:

windows默认是gbk,一般不需要变动。不过大家又想每个文件都要建立为utf8格式怎么办,不可能我们每个文件建立后都去用属性改变一下?太麻烦!直接在eclipse设置后,同种类型的文件建立都会是utf8格式。

eclipse属性2

 

linux,可以有两个地方修改基本就足够了:

vi /etc/sysconfig/i18n

修改

  1. LANG="zh_CN.GB3212" 
  2. LANGUAGE="zh_CN.GB18030:zh_CN.GB2312:zh_CN" 
  3. SUPPORTED="zh_CN.GB18030:zh_CN:zh:en_US.UTF-8:en_US:en" 

vi /etc/profile

  1. export LC_ALL="zh_CN.GB2312" 
  2. export LANG="zh_CN.GB2312" 

原文链接:http://www.lanceyan.com/tech/arch/web_luanma.html

责任编辑:陈四芳 来源: lanceyan.com
相关推荐

2011-05-16 13:15:55

MySQL存储字符集

2010-05-17 10:01:09

MySql字符集

2010-06-11 16:46:20

MySQL5

2009-07-01 00:23:40

MySQL字符集乱码

2010-04-30 10:16:22

Oracle字符集

2011-02-24 09:27:00

Java字符集编码

2011-04-11 10:59:33

Oracle字符集

2010-04-21 16:07:16

Oracle 8i

2011-04-11 11:05:12

Oracle字符集

2010-04-22 09:08:30

Oracle 8i

2010-06-13 10:06:05

MySQL4.1.7

2020-12-16 06:34:16

MySQL字符集服务器

2021-03-23 18:21:30

MySQL数据库字符集

2010-06-07 16:09:58

MySQL字符集

2010-06-10 13:34:17

MySQL5

2010-06-02 17:59:19

MySQL字符集

2011-05-20 13:24:39

oracle字符集

2009-11-20 16:52:35

Oracle字符集

2010-04-28 17:29:07

Oracle字符集

2010-06-13 16:17:26

MySQL改变字符集
点赞
收藏

51CTO技术栈公众号