学科分类
目录
Java Web

中文输出乱码问题

由于计算机中的数据都是以二进制形式存储的,因此,当传输文本时,就会发生字符和字节之间的转换。字符与字节之间的转换是通过查码表完成的,将字符转换成字节的过程称为编码,将字节转换成字符的过程称为解码,如果编码和解码使用的码表不一致,就会导致乱码问题。接下来,通过一个案例来演示产生乱码的情况,如例1所示。

例1 ChineseServlet.java

 1    package cn.itcast.chapter05.response; 
 2    import java.io.*;
 3    import javax.servlet.*;
 4    import javax.servlet.http.*;
 5    public class ChineseServlet extends HttpServlet {
 6        public void doGet(HttpServletRequest request,
 7                HttpServletResponse response) throws ServletException, 
     IOException {
 8            String data="中国";
 9            PrintWriter out = response.getWriter();   
 10            out.println(data);
 11        }
 12        public void doPost(HttpServletRequest request,
 13                HttpServletResponse response) throws ServletException, 
     IOException {
 14            doGet(request,response);
 15        }
 16    }

在web.xml中配置完ChineseServle映射后,启动Tomcat服务器,在浏览器的地址栏中输入URL地址http://localhost:8080/chapter05/ChineseServlet访问ChineseServlet,浏览器显示的结果如图1所示。

图1 运行结果

从图1中可以看出,浏览器显示的内容都是“?”,说明发生了乱码问题。通过分析发现,response对象的字符输出流在编码时,采用的是iso8859-1的字符码表,该码表并不兼容中文,会将“中国”编码为“63 63”(在iso8859-1的码表中若查不到字符就会显示63)。当浏览器对接收到的数据进行解码时,会采用默认的码表gb2312,将“63 ”解码为“?”,因此,浏览器将“中国”两个字符显示成了“??”,具体分析如图2所示。

图2 编码错误分析

为了解决上述编码错误,在HttpServletResponse接口中,提供了一个setCharacterEncoding()方法,该方法用于设置字符的编码方式,接下来对例5-2进行修改,在第7行代码和第8行之间增加一行代码,设置字符编码使用的码表为utf-8,代码具体如下:

response.setCharacterEncoding("utf-8");

在浏览器的地址栏中输入URL地址http://localhost:8080/chapter05/ChineseServlet再次访问ChineseServlet,浏览器显示的结果如图3所示。

图3 运行结果

从图3可以看出,浏览器中显示的乱码虽然不是“?”,但也不是我们希望输出的“中国”。通过分析发现,这是由浏览器解码错误导致的。因为response对象的字符输出流设置的编码方式为utf-8,而浏览器使用的解码方式是gb2312,具体分析过程如图4所示。

图4 解码错误分析

对于图4所示的解码错误,可以通过修改浏览器的解码方式解决。在浏览器中点击【查看】à【编码】à【utf-8】选项,将浏览器的编码方式设置为utf-8,浏览器的显示结果如图5所示。

图5 运行结果

从图5中可以看出,浏览器显示的内容没有出现乱码,由此说明,通过修改浏览器的编码方式可以解决乱码,但是,这样的做法显然不可取,为此,在HttpServletResponse对象中,提供了两种解决乱码的方案,具体如下:

第一种方式:

// 设置HttpServletResponse使用utf-8编码
response.setCharacterEncoding("utf-8"); 
// 通知浏览器使用utf-8解码
response.setHeader("Content-Type","text/html;charset=utf-8"); 

第二种方式:

// 包含第一种方式的两个功能
response.setContentType("text/html;charset=utf-8"); 

通常情况下,为了使代码更加简洁,我们采用第二种方式。接下来,对例1进行修改,使用HttpServletResponse对象的第二种方式来解决乱码问题,修改后的代码如例2所示。

例2 ChineseServlet.java

 1    package cn.itcast.chapter05.response;
 2    import java.io.*;
 3    import javax.servlet.*;
 4    import javax.servlet.http.*;
 5    public class ChineseServlet extends HttpServlet {
 6        public void doGet(HttpServletRequest request,
 7                HttpServletResponse response) throws ServletException, 
     IOException {
 8            String data="中国";
 9             response.setContentType("text/html;charset=utf-8");
 10            PrintWriter out = response.getWriter();
 11            out.println(data);
 12        }
 13        public void doPost(HttpServletRequest request,
 14                HttpServletResponse response) throws ServletException, 
     IOException {
 15            doGet(request,response);
 16        }
 17    }

启动Tomcat服务器,在浏览器的地址栏中输入URL地址http://localhost:8080/chapter05/ChineseServlet访问ChineseServlet,浏览器显示出了正确的中文字符,如图6所示。

图6 运行结果

点击此处
隐藏目录