`
啸笑天
  • 浏览: 3466019 次
  • 性别: Icon_minigender_1
  • 来自: China
社区版块
存档分类
最新评论

java乱码

    博客分类:
  • jsp
阅读更多

二、中文字符乱码的原因及解决办法 

java的内核是Unicode的,也就是说,在程序处理字符时是用Unicode来表示字符的,但是文件和流的保存方式是使用字节流的。在java的基本数据类型中,char是Unicode的,而byte是字节,因此,在不同的环节java要对字节流和char进行转换。这种转换发生时如果字符集的编码选择不当,就会出现乱码问题。 

我们常见的乱码大致有如下几种情形:
1、汉字变成了问号"?"
2、有的汉字显示正确,有的则显示错误
3、显示乱码(有些是汉字但并不是你预期的)
4、读写数据库出现乱码 

下面我们逐一对它们出现的原因做一些解释: 

首先,我们讨论汉字变成问号的问题。 

Java中byte与char相互转换的方法在sun.io包中。其中,byte到char的常用转换方法是:
public static ByteToCharConverter getConverter(String encoding); 

为了便于大家理解,我们先来做一个小实验:比如,汉字"你"的GBK编码为0xc4e3,其Unicode编码是\u4f60。我们的实验是这样的,先有一个页面比如名为a_gbk.jsp输入汉字"你",提交给页面b_gbk.jsp。在b_gbk.jsp文件中以某种编码方式得到"你"的字节数组,再将该数组以某种编码方式转换成char,如果得到的char值是0x4f60则转换是正确的。 

a_gbk.jsp的代码如下: 

<%@ page contentType="text/html; charset=GBK" language="java" import="java.sql.*" errorPage="" %>
<table width="611" border="0" align="center" cellpadding="0" cellspacing="0">
  <tr>
    <td>&nbsp;</td>
    <td class="bigword">&nbsp;</td>
    <td>&nbsp;</td>
  </tr>
  <tr>
    <td width="100">&nbsp;</td>
    <td class="bigword">Input</td>
    <td width="100">&nbsp;</td>
  </tr>
  <tr>
    <td>&nbsp;</td>
    <td class="bigword">&nbsp;</td>
    <td>&nbsp;</td>
  </tr>
</table>
<table width="611" border="0" align="center" cellpadding="0" cellspacing="0">
  <tr>
    <td><form method="post" action="b_gbk.jsp">
        <table width="611" border="0" cellpadding="0" cellspacing="0">
          <tr>
            <td width="100" align="right"></td>
            <td><input name="ClsID" type="text" class="word" id="ClsID" maxlength="2" >
              *</td>
          </tr>
          <tr>
            <td width="100" align="right">&nbsp;</td>
            <td><input name="btn" type="submit" value="OK">
             </td>
          </tr>
        </table>
      </form></td>
  </tr>
</table>


b_gbk.jsp的代码如下: 

<%@ page contentType="text/html; charset=GBK" import="sun.io.*,java.util.*" %>
<%
String a=(String)request.getParameter("ClsID");
byte b[]=a.getBytes("ISO8859-1");
for(int j=0;j<b.length;j++){
  out.println(Integer.toHexString(b[j])+"<br>");
}
ByteToCharConverter convertor=ByteToCharConverter.getConverter("GBK");
char[] c=convertor.convertAll(b);
out.println("b length:"+b.length+"<br>");
out.println("c length:"+c.length+"<br>");
for(int i=0;i<c.length;i++){
 	out.println(Integer.toHexString(c[i])+"<br>");
}
String a1=new String(a.getBytes("ISO8859-1"),"GBK");
%>
<%="a是:"+a%><br>
<%="a1是:"+a1%>


在浏览器中打开a_gbk.jsp并输入一个"你"字,点击OK按钮提交表单,则会出现如图1所示的结果: 

 

图1 

从图1可以看出,在b_gbk.jsp中这样将byte转换为char是正确的,即得到的char是\u4f60。这里要注意的是:byte b[]=a.getBytes("ISO8859-1");中的编码是ISO8859-1,这就是我们前面提到的有些web容器在您没有指定request的字符集时它就采用缺省的ISO8859-1。 

从图1中我们还看到表达式中的a并没有正确地显示"你"而是变成"??"这是什么原因呢?这里的a是作为一个String被显示的,我们来看看我们常用的String构造函数: 

String(byte[] bytes,String encoding); 
在国标平台上,该函数会认为bytes是按GBK编码的,如果后一个参数省略,它也会认为是encoding是GBK。 


对前一个参数就相当于将b_gbk.jsp文件的这句byte b[]=a.getBytes("ISO8859-1");中的ISO8859-1改为GBK,这样显然在GBK字符集中找不到相应的目的编码,它给出的结果是0x3f、0x3f。因此,就会显示为"??",这也就是造成乱码的第一种现象的原因。我们的例子是演示的从byte到char的转换过程,相反的过程也会造成同样的问题,限于篇幅,就不在此讨论了,大家自己可以做类似的实验来验证。 

解决该问题的方法就是象例子中a1那样,在获取byte数组时,指定编码为ISO8859-1。 

接下来,我们讨论有些汉字能正常显示,有些不能正常显示的问题。 

如果我们将String a1=new String(a.getBytes("ISO8859-1"),"GBK");中的GBK改为GB2312则象朱镕基的"镕"字就不能正常显示,这是因为该字是GBK中的字符而在GB2312中不存在。 

解决上述两种问题的方法就是象a1那样构造String,也就是人们常说的同时也是常用的转码的方法。采用这种方法会在程序中到处出现这种语句,特别是在Struts中,Struts有一个回写表单的功能,在回写时也要做这种转换,这样的语句差不多要多一倍。因此,这是个比较笨拙的方法,有没有简捷一些的方法呢?其实是有的,只要在取得request的字符串前加上request.setCharacterEncoding("GBK");这句,指定request的字符集。则中的a就能正常显示,a1反而不能正常显示。此时要将byte b[]=a.getBytes("ISO8859-1");中的ISO8859-1变成GBK,从byte到char的转换才是正确的,这就是此时a能正常显示而a1反而不能正常显示的原因。如果此时要a1正常显示则必须将String a1=new String(a.getBytes("ISO8859-1"),"GBK");中的ISO8859-1改为GBK。 

很显然,使用request.setCharacterEncoding("GBK");只能解决GBK字符问题,要解决i18n问题则要使用UTF-8来取代GBK。我们接着做上述实验,将a_gbk.jsp和b_gbk.jsp分别另存为a.jsp和b.jsp将文件中的GBK改为UTF-8,更改后的代码分别如下: 

a.jsp代码: 

<%@ page contentType="text/html; charset=UTF-8" language="java" import="java.sql.*" errorPage="" %>

<table width="611" border="0" align="center" cellpadding="0" cellspacing="0">
  <tr>
    <td>&nbsp;</td>
    <td class="bigword">&nbsp;</td>
    <td>&nbsp;</td>
  </tr>
  <tr>
    <td width="100">&nbsp;</td>
    <td class="bigword">Input</td>
    <td width="100">&nbsp;</td>
  </tr>
  <tr>
    <td>&nbsp;</td>
    <td class="bigword">&nbsp;</td>
    <td>&nbsp;</td>
  </tr>
</table>
<table width="611" border="0" align="center" cellpadding="0" cellspacing="0">
  <tr>
    <td><form method="post" action="b.jsp">
        <table width="611" border="0" cellpadding="0" cellspacing="0">
          <tr>
            <td width="100" align="right"></td>
            <td><input name="ClsID" type="text" class="word" id="ClsID" maxlength="2" >
              *</td>
          </tr>
          <tr>
            <td width="100" align="right">&nbsp;</td>
            <td><input name="btn" type="submit" value="OK">
             </td>
          </tr>
        </table>
      </form></td>
  </tr>
</table>
b.jsp代码:
<ccid_nobr>
<table width="400" border="1" cellspacing="0" cellpadding="2" 
 bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center">
<tr>
    <td bgcolor="e6e6e6" class="code" style="font-size:9pt">
    <pre><ccid_code>  <%@ page contentType="text/html; charset=UTF-8" import="sun.io.*,java.util.*" %>

<%
request.setCharacterEncoding("UTF-8");
String a=(String)request.getParameter("ClsID");
byte b[]=a.getBytes("UTF-8");
for(int j=0;j<b.length;j++){
  out.println(Integer.toHexString(b[j])+"<br>");
}
ByteToCharConverter convertor=ByteToCharConverter.getConverter("UTF-8");
char[] c=convertor.convertAll(b);
out.println("b length:"+b.length+"<br>");
out.println("c length:"+c.length+"<br>");
for(int i=0;i<c.length;i++){
  out.println(Integer.toHexString(c[i])+"<br>");
}
String a1=new String(a.getBytes("UTF-8"),"UTF-8");
%>
<%="a是:"+a%><br>
<%="a1是:"+a1%>


再在a.jsp中输入"你"字,你会发现显示结果中,一个汉字是用三个byte表示的,它们的值分别是0xe4、0xbd、0xa0,也就是说用UTF-8来表示汉字,每个汉字要比GBK多占用一个byte,这也是使用UTF-8要多付出的一点代价吧。 

现在,我们讨论一下第三个问题,即显示乱码,有些莫名其妙的汉字并不是你预期的结果。 

在上例中将String a1=new String(a.getBytes("UTF-8"),"UTF-8");改为String a1=new String(a.getBytes("UTF-8"),"GBK");再输入"你"字,则a1会显示成"浣?",您只要看一看"浣"的UTF-8码和GBK码就会知道其中的奥秘了。 

下面,我们讨论一下最后一个问题,就是读写数据库时出现乱码。 

现在一些常用的数据库都支持数据库encoding,也就是说在创建数据库时可以指定它自己的字符集设置,数据库数据以指定的编码形式存储。当应用程序访问数据库时,在入口和出口处都会有encoding转换。如果,在应用程序中字符本来已变成了乱码,当然也就无法正确地转换为数据库的字符集了。数据库的encoding可根据需要来设置,比如要支持简、繁体中文、日、韩、英语选GBK,如果还要支持其他语言最好选UTF-8。 

分享到:
评论

相关推荐

    java乱码解决方法

    解决java web开发中遇到的前后台传值乱码问题。

    java乱码处理

    ### Java中文乱码处理 #### 一、Java中文问题的由来 Java作为一种跨平台的编程语言,其内部实现和class文件均基于Unicode编码,这为Java程序带来了优秀的跨平台特性。然而,这也同时带来了一些关于中文乱码的问题...

    Java乱码问题解决方法

    Java乱码问题解决方法,java乱码怎么解决,java项目乱码,java乱码处理,

    java乱码问题解决方法

    Java 乱码问题是 Java 开发中常见的问题之一,解决这个问题需要了解 Java 的编码方式、JSP 中文乱码问题、Tomcat 5.5 中文乱码问题、JDBC ODBC Bridge 的 Bug 及其解决方法、Solaris 下 Servlet 编程的中文问题及...

    java乱码转换

    java 乱码 转换 utf

    Java乱码问题

    ### Java乱码问题详解 #### 问题描述与背景 在Java开发过程中,遇到“文件名.java:1: 错误: 编码GBK的不可映射字符”这类问题较为常见,尤其是在处理包含中文字符的代码文件时。这个问题通常出现在Windows操作系统...

    Java中文乱码浅析及解决方案

    Java 中文乱码问题是一个常见的编程困扰,尤其对于处理中文字符的Java程序而言。这个问题通常源于字符编码的不一致,即不同环节采用的字符编码标准不统一。本文将深入探讨这一问题,并提供相应的解决方案。 首先,...

    JAVA 乱码

    JAVA 乱码

    Java乱码解决方案

    以下是一些关于Java乱码解决方案的关键知识点: 1. **字符编码基础**:首先要理解的是字符编码,如ASCII、GBK、UTF-8等。ASCII只支持英文字符,GBK是中国常用的扩展GBK编码,而UTF-8是通用的多字节编码,能支持全...

    java中常见的中文乱码总结

    Java 中文乱码总结 Java 中文乱码是指在 Java 应用程序中出现的中文字符显示不正确的问题。这种问题的出现是由于编码方式的不同引起的。下面我们将详细介绍 Java 中文乱码的原因、解决方法和防止乱码的技巧。 一、...

    java乱码自己解决的办法

    本文将深入探讨Java乱码的根源,并提供一系列实用的解决方案,帮助开发者有效应对这一挑战。 ### Java乱码根源 Java乱码主要由编码不一致引起,具体来说,当数据在不同环境(如输入、存储、读取)中采用不同的字符...

    java乱码终极必杀技

    本篇文章将深入探讨Java乱码问题的解决方法,为你提供终极必杀技。 首先,我们需要了解编码的基础知识。ASCII是最早的基础字符集,包含128个字符,而Unicode则是包含了世界上大多数语言字符的编码标准,如UTF-8、...

    java中文乱码大全

    Java中文乱码问题是编程者在开发Java应用程序时经常遇到的问题,尤其是涉及到中文字符处理时。这些问题产生的根本原因在于Java内部采用UNICODE编码,而不同的操作系统和浏览器可能支持不同的编码格式,如Windows中文...

    Java乱码问题解决

    ### Java乱码问题详解与解决方案 #### 一、问题背景 在Java开发过程中,尤其是在处理中文字符时,经常遇到字符编码不一致导致的乱码问题。由于Java默认使用Unicode编码,而在中国大陆地区,常见的字符集为GB2312...

    java URL乱码的解决办法

    Java URL 乱码问题在开发过程中常常困扰开发者,尤其是在处理包含中文字符的URL时。URL乱码通常是由于编码和解码过程中的不匹配所引起的。本文将深入探讨这个问题,并提供几种有效的解决方法。 首先,我们需要了解...

    java乱码问题的解决

    当你编写代码时是不是也遇到了乱码问题 尤其是jquery post提交 来下载看看吧 你会有所收获 (个人总结 针对不同情况)

    java乱码问题

    在探讨“Java乱码问题”这一主题时,我们首先需要理解字符编码的基本概念以及它在Java编程中的应用。字符编码是计算机系统用来表示文本的一种方式,它将字符映射为特定的二进制数,以便于存储和传输。常见的字符编码...

    java邮件乱码的彻底解决方案

    Java邮件乱码问题一直是开发过程中常见的困扰之一,尤其是在发送包含中文字符的邮件时。本文将深入探讨Java邮件乱码的成因以及如何找到彻底解决这一问题的方法。 首先,我们需要了解邮件编码的基本原理。电子邮件...

    JAVA中文乱码

    解决java前端页面和后端代码的中文乱码的问题,在我的百度文档上也有说明

Global site tag (gtag.js) - Google Analytics