hjack 发表于 2005-9-18 18:30

[原创]中文问题的解决方法实现一例

一直没有网上,今天中秋节,56K小猫送上一篇文章,祝大家中秋快乐。


这篇文章是参考了网上的意见后在本人的实际应用开发中证明是切实可行的。

1、因为java就是基于utf-8的,对于双字节的中文(或其它外文)一律看成是utf-8编码来处理,所以在web.xml文件里添加以下代码:

        <filter>
                <filter-name>Set Character Encoding</filter-name>
                <filter-class>com.hjackstudio.forum.util.SetCharacterEncodingFilter</filter-class>
                <init-param>
                        <param-name>encoding</param-name>
                        <param-value>UTF-8</param-value>
                </init-param>
        </filter>

<filter>是<web-app>下的元素。

2、com.hjackstudio.forum.util.SetCharacterEncodingFilter代码如下:

    /*
   * 创建日期 2005-8-29
   *
   * 更改所生成文件模板为
   * 窗口 > 首选项 > Java > 代码生成 > 代码和注释
   */
    package com.hjackstudio.forum.util;
   
    import java.io.IOException;
   
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
   
    /**
   * @author hjack
   *
   * 更改所生成类型注释的模板为
   * 窗口 > 首选项 > Java > 代码生成 > 代码和注释
   */
    public class SetCharacterEncodingFilter implements Filter {
   
            protected String encoding = null;
   
            protected FilterConfig filterConfig = null;
   
            protected boolean ignore = true;
           
            /* (非 Javadoc)
           * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
           */
            public void init(FilterConfig filterConfig) throws ServletException {
                    // TODO 自动生成方法存根
                    //使用配置的方法从web.xml中读入编码信息,避免硬编码。
                    this.filterConfig = filterConfig;
                    this.encoding = filterConfig.getInitParameter("encoding");
                    String value = filterConfig.getInitParameter("ignore");
                    if (value == null) {
                      this.ignore = true;
                    }
                    else if (value.equalsIgnoreCase("true")) {
                      this.ignore = true;
                    }
                    else if (value.equalsIgnoreCase("yes")) {
                      this.ignore = true;
                    }
                    else {
                      this.ignore = false;
                    }
   
            }
   
            /* (非 Javadoc)
           * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
           */
            public void doFilter(
                    ServletRequest request,
                    ServletResponse response,
                    FilterChain chain)
                    throws IOException, ServletException {
                    // TODO 自动生成方法存根
                    if (ignore || (request.getCharacterEncoding() == null)) {
                            String encoding = selectEncoding(request);
                            if (encoding != null) {
                            //正是通过这句代码实现的。
                                    request.setCharacterEncoding(encoding);
                            }
                    }   
                    // Pass control on to the next filter
                    chain.doFilter(request, response);       
            }
   
   
            protected String selectEncoding(ServletRequest request) {
   
              return (this.encoding);
   
            }
           
            /* (非 Javadoc)
           * @see javax.servlet.Filter#destroy()
           */
            public void destroy() {
                    // TODO 自动生成方法存根
                    this.encoding = null;
                    this.filterConfig = null;
            }
   
            public static void main(String[] args) {
            }
    }


3、在jsp页面中使用<%@ page contentType="text/html;charset=UTF-8" language="java" %>,就可以解决页面的中文显示了。

4、当提交表单插入中文到数据库时,还要使用以下方法才可以正确插入和读出。 我使用的是hibernate和mysql,在hibernate.cfg.xml文件里的数据连接属性里用上以下这句:<property name="connection.url">jdbc:mysql://localhost/forum?useUnicode=true&amp;characterEncoding=GBK</property>
注意:characterEncoding=GBK 指定了GBK就可以对中文进行操作了。

wool王 发表于 2005-9-19 01:42

帮你补充个过滤器映射。。。

<filter-mapping>          
<filter-name>Set Character Encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

jackvenn 发表于 2005-9-19 15:40

对了,忘了贴这个了,哈哈

寂寞高手 发表于 2005-9-19 18:43

<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>
建议用
<%@ page contentType=\"text/html;charset=gb2312\" language=\"java\" %>啊

其实UTF-8是专门用在 url 地址传送中文的一种编码,google就是用这个的。

hjack 发表于 2005-9-19 23:07

用utf-8是因为要解决国际化问题,而不只是中文问题。

寂寞高手 发表于 2005-9-20 10:49

恩。 。。是的

wool王 发表于 2005-9-21 21:17

utf8是国际码

sasadong 发表于 2005-11-8 21:08

Originally posted by wool王 at 2005-9-21 21:17:
utf8是国际码


看来大家对字符集不是很懂。(在这里我明确区分编码和字符集,因为他们是不同的,虽然我们经常把他们混为一谈)

字符集其实是一种把映射,是文字到二进制数据的映射。
例如:我们熟悉的ascii码,就是
0 -> 0x30
1 -> 0x31
...
的映射。

这里的文字,可以是单个汉字、字母、数字、符号、标点、等等。

下面是几种常见的字符集:

iso-8859-1,其文字范围主要就是我们键盘上所看到的还有部分不可打印的控制字符,二进制范围只用了1个字节,值是十进制的0-255。也叫latin字符集。ascii是它的子集(0-127)。

gb2312,是国标码(比较少的),其文字范围涵盖比较常见的简体字以及标点符号,其二进制采用两个字节,为了与ascii兼容,gb2312码的每个字节十进制值总是大于127,这样就保留了127以下的值区间给ascii字符使用。

gbk码,是在gb2312基础上设计的,比gb2312包含更多字符的字符集,也叫大字符集。

big5码。大5码是港台地区普遍使用的字符集,类似gb2312码,也是采用两个字节,也是与ascii码兼容(每字节都要大于127以保留127以下给ascii使用)。这个字符集的映射与gb2312不同,即假设gb2312“你”的映射使用big5来反映射得到的不是繁体的“妳”,而是另外一个字。

unicode字符集,unicode字符集分为两个标准,一个称为UCS-2,另外一个是UCS-4。前一个是采用两个字节,即16位,后面一个使用了32位4个字节。因而后面的标准可以容纳数百万个文字。目前两个标准的内容是基本一致的,即UCS-2的内容和UCS-4的低两字节一样,UCS-4的高两字节填0,UCS-4庞大的字符集空间做好对未来扩充的准备,但现在使用4字节来存储一个文字显得浪费,因而一般都使用UCS-2标准存储。我们所说的Unicode在没有明确说明情况下也仅指使用2字节的UCS-2。

utf-8,严格来说,这不是一个字符集,而是一个编码。这是一个用于传输unicode字符的编码方案。(也因为其特殊应用,所以这个编码有了唯一的集合,一般都看作字符集)。utf-8这个8是指使用8位的前导.前面说了,127以下的是属于ascii字符集,其实Unicode字符集的0x0000-0x007f与ascii是兼容的。0-127可形容为0x00-0x7f,其最高位(传输使用高位开始传,是最前一位)是0,则代表应当解析为1个字节的ascii字符。如果最前是110xxxxx,则代表组成这个文字值的总共有2个字节,其后面一个字节必须是10xxxxxx的形式,这些x就用Unicode字符集中的值从左到右填充。具体的填充方法(抄来如下):
U-00000000 - U-0000007F:0xxxxxxx
U-00000080 - U-000007FF:110xxxxx 10xxxxxx
U-00000800 - U-0000FFFF:1110xxxx 10xxxxxx 10xxxxxx
U-00010000 - U-001FFFFF:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U-00200000 - U-03FFFFFF:111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U-04000000 - U-7FFFFFFF:1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx


乱码的形成,要让浏览器正确显示网页,主要有两点:
1,网站输出的字符集必须是浏览器所在系统安装有的字符集,如网站输出big5字符集,而我们机子没有安装big5码,则无论如何是显示不正常的。
2,网站数尺的内容,还有浏览器使用正确的字符集解析。这就需要网页制作者在http协议头(header)声明正确的charset,以及在输出的html声明charset(两个地方)。两个charset一致。同时保证网页包含的内容使用的字符集一致,这又与数据库输出的内容相关联,(所以还要保证数据库保存的数据使用与网页一致的字符集)。

如楼主所说,全部使用utf-8是一个解决方法。但却不是最好的方法。为什么?这个问题十分复杂,说起来一大堆。但有一个最简单的常识:我们中国人的操作系统最常用的字符集是gb2312而不是utf-8。

sasadong 发表于 2005-11-8 21:20

我们在编写web脚本程序时,如jsp,我们写“hello你好”这个字符串,如果我们使用java ide编写,这些文字保存时可能会自动采用unicode字符集。
如果我们仅仅是使用ultraedit-32编辑器,那么根据你操作系统的默认字符集,保存的就十分可能是gb2312。

一般来说,javac编译命令应该能够对这种使用gb2312字符集保存的java文件自动转码成utf-8来编译。呵呵,想当然是十分好的,至少不会烦。但如果不能够,那乱码会让你更烦。

实际上,java编译器跟当前操作系统的默认字符集有莫大关联(我使用Linux Enterpise AS 4),我在弄tomcat时经常遇到java编译器不会自动转码导致的乱码问题。


这个也是为什么我后来较多使用php的原因,因为我经常用vi写程序,而这对java 来说,是所有乱码的一个根源。我喜欢php不作修饰的裸露。我用的字符集我作主。。。使用php之下,想乱码,还是很难D。

大鱼 发表于 2005-11-11 22:12

楼主的文章不错。
狂顶一下。

这样的中文问题我想不单是JAVA语言会发生。ASP,NET系列也有同样的错误。
我在ASP中就遇到过。解决办法和楼主的基本相同。
NET方面的程序解决办法就容易多了。
只要获取时候,设置根据特定的编码获取相应的值就可以了。

iptton 发表于 2006-12-19 14:30

翻旧帖让我翻着了....

先顶上来,再加分...

iptton 发表于 2006-12-19 14:30

翻旧帖让我翻着了....

先顶上来,再加分...
================

系统原因,回了两帖。。。

PHP+MYSQL时还是会遇到乱码问题...不过找资料乱弄一通搞掂了
但下次再遇上恐怕又要找资料
遇问题再上这里请教各位师兄

[ 本帖最后由 iptton 于 2006-12-19 14:39 编辑 ]
页: [1]
查看完整版本: [原创]中文问题的解决方法实现一例