`
dtrex
  • 浏览: 139541 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论
阅读更多

http://www.blogjava.net/nokiaguy/archive/2008/07/19/216024.html

 

 

 

此刻打盹,你将做梦;而此刻学习,你将圆梦。

Java编码问题解决方案大揭密

本文为原创,如需转载,请注明作者和出处,谢谢!

<!-- [if gte mso 9]><xml> Normal 0 7.8 磅 0 2 false false false MicrosoftInternetExplorer4 </xml><![endif]--><!-- [if gte mso 9]><![endif]--> <!-- /* Font Definitions */ &#64;font-face {font-family:Batang; panose-1:2 3 6 0 0 1 1 1 1 1;} &#64;font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1;} &#64;font-face {font-family:""&#64;宋体"; panose-1:2 1 6 0 3 1 1 1 1 1;} &#64;font-face {font-family:""&#64;Batang"; panose-1:2 3 6 0 0 1 1 1 1 1;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; font-size:10.5pt; font-family:"Times New Roman";} /* Page Definitions */ &#64;page {} &#64;page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt;} div.Section1 {page:Section1;} --> <!-- [if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable { mso-style-parent:""; font-size:10.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman";} </style> <![endif]-->

一、 Java 编码是怎么回事?

对于使用中文以及其他非拉丁语系语言的开发人员来说,经常会遇到字符集编码问题。对于 Java语言来说,在其内部使用的是 UCS2编码( 2个字节的 Unicode编码)。这种编码并不属于某个语系的语言编码,它实际上是一种编码格式的世界语。在这个世界上所有可以在计算机中使用的语言都有对应的 UCS2编码。

正是因为 Java采用了 UCS2,因此,在 Java中可以使用世界上任何国家的语言来为变量名、方法名、类起名,如下面代码如下:


<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->class  中国
{
    
public  String 雄起()
    {
         
return   " 中国雄起 " ;
    }
}

中国 祖国 
=   new  中国();
System.out.println(祖国.雄起());

    哈哈,是不是有点象“中文编程”。实际上,也可以使用其他的语言来编程,如下面用韩文和日文来定义个类:

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->class  수퍼맨
{
    
public   void  スーパーマン() {   }
}

    实际上,由于 Java内部使用的是 UCS2编码格式,因为, Java并不关心所使用的是哪种语言,而只要这种语言在 UCS2中有定义就可以。

    UCS2编码中为不同国家的语言进行了分页,这个分页也叫“代码页”或“编码页”。中文根据包含中文字符的多少,分了很多代码页,如 cp935 cp936等,然而,这些都是在 UCS2中的代码页名,而对于操作系统来说,如微软的 windows,一开始的中文编码为 GB2312,后来扩展成了 GBK。其实 GBK cp936是完全等效的,用它们哪个都行。

二、 Java 编码转换

   
上面说了这么多,在这一部分我们做一些编码转换,看看会发生什么事情。

    先定义一个字符串变量:

    String gbk = "
中国 "; // “中国”在 Java内部是以 UCS2格式保存的

    用下面的语言输出一定会输出中文:

System.out.println(gbk);

    实现上,当我们从 IDE输入“中国”时,用的是 java源代码文件保存的格式,一般是 GBK,有时也可是 utf-8,而在 Java编译程序时,会不由分说地将所有的编码格式转换成 utf-8编码,读者可以用 UltraEdit或其他的二进制编辑器打开上面的“中国 .class”,看看所生成的二进制是否有 utf-8的编码( utf-8 ucs2之间的转换非常容易,因为 utf-8 ucs2之间是用公式进行转换的,而不是到代码页去查,这就相当于将二进制转成 16进制一样, 4个字节一组)。如“中国”的 utf-8编码按着 GBK解析就是“涓   浗 ”。如下图所示。



<!-- [if gte mso 9]><xml> Normal 0 7.8 磅 0 2 false false false MicrosoftInternetExplorer4 </xml><![endif]--><!-- [if gte mso 9]><![endif]--> <!-- /* Font Definitions */ &#64;font-face {font-family:Batang; panose-1:2 3 6 0 0 1 1 1 1 1;} &#64;font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1;} &#64;font-face {font-family:""&#64;宋体"; panose-1:2 1 6 0 3 1 1 1 1 1;} &#64;font-face {font-family:""&#64;Batang"; panose-1:2 3 6 0 0 1 1 1 1 1;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; font-size:10.5pt; font-family:"Times New Roman";} /* Page Definitions */ &#64;page {} &#64;page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt;} div.Section1 {page:Section1;} --> <!-- [if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable { mso-style-parent:""; font-size:10.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman";} </style> <![endif]-->

如果使用下面的语言可以获得“中国”的 utf-8字节,结果是 6(一个汉字由 3个字节组成)

System.out.println(gbk.getBytes("utf-8").length);

下面的代码将输出“涓   浗 ”。

System.out.println(new String(gbk.getBytes("utf-8"), "gbk"));   

由于将“中国“的 utf-8编码格式按着 gbk解析,所以会出现乱码。

如果要返回中文的 UCS2编码,可以使用下面的代码:

System.out.println(gbk.getBytes("unicode")[2]);

System.out.println(gbk.getBytes("unicode")[3]);

前两个字节是标识位,要从第 3个字节开始。还有就是其他的语言使用的编码的字节顺序可能不同,如在 C#中可以使用下面的代码获得“中国“的 UCS2编码:

String s = "
";

MessageBox.Show(ASCIIEncoding.Unicode.GetBytes(s)[0].ToString());

MessageBox.Show(ASCIIEncoding.Unicode.GetBytes(s)[1].ToString());

    使用上面的 java代码获得的“中“的 16进制 UCS2编码为 4E2D,而使用 C#获得的相应的 ucs2编码为 2D4E,这只是 C# Java编码内部使用的问题,并没有什么关系。但在 C# Java互操作时要注意这一点。

    如果使用下面的 java编码将获得 16进制的“中”的 GBK编码:

System.out.println(Integer.toHexString(0xff & xyz.getBytes("gbk")[0]));

System.out.println(Integer.toHexString(0xff & xyz.getBytes("gbk")[1]));

“中”的 ucs2编码为 2D4E GBK编码为 D6D0

    读者可访问如下的 url自行查验:

    http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP936.TXT

    当然,感兴趣的读者也可以试试其他语言的编码,如“人类”的韩语是“ 인간의 ”,如下面的代码将输出“ 인간의 ”的 cp949 ucs2编码,其中 cp949是韩语的代码页。


<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->String korean  =   " 인간의 " //  共三个韩文字符,我们只测试第一个“인”

System.out.println(Integer.toHexString(
0xff   &  korean.getBytes( " unicode " )[ 2 ]));

System.out.println(Integer.toHexString(
0xff   &  korean.getBytes( " unicode " )[ 3 ]));

System.out.println(Integer.toHexString(
0xff   &  korean.getBytes( " Cp949 " )[ 0 ]));

System.out.println(Integer.toHexString(
0xff   &  korean.getBytes( " Cp949 " )[ 1 ]));

 

上面代码的输出结果如下:

<!-- [if gte mso 9]><xml> Normal 0 7.8 磅 0 2 false false false MicrosoftInternetExplorer4 </xml><![endif]--><!-- [if gte mso 9]><![endif]--> <!-- /* Font Definitions */ &#64;font-face {font-family:Batang; panose-1:2 3 6 0 0 1 1 1 1 1;} &#64;font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1;} &#64;font-face {font-family:""&#64;宋体"; panose-1:2 1 6 0 3 1 1 1 1 1;} &#64;font-face {font-family:""&#64;Batang"; panose-1:2 3 6 0 0 1 1 1 1 1;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; font-size:10.5pt; font-family:"Times New Roman";} /* Page Definitions */ &#64;page {} &#64;page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt;} div.Section1 {page:Section1;} --> <!-- [if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable { mso-style-parent:""; font-size:10.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman";} </style> <![endif]-->

c7

78

c0

ce

    也就是说“ ”的 ucs2 编码为 C778 cp949 的编码为 C0CE ,要注意的是,在 cp949 中, ucs2 编码也有 C0CE ,不要弄混了。读者可以访问下面的 url 来验证:

http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP949.TXT
<!-- [if gte mso 9]><xml> Normal 0 7.8 磅 0 2 false false false MicrosoftInternetExplorer4 </xml><![endif]--><!-- [if gte mso 9]><![endif]--><!-- [if !mso]> <style> st1":*{behavior:url(#ieooui) } </style> <![endif]--> <!-- /* Font Definitions */ &#64;font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1;} &#64;font-face {font-family:""&#64;宋体"; panose-1:2 1 6 0 3 1 1 1 1 1;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; font-size:10.5pt; font-family:"Times New Roman";} /* Page Definitions */ &#64;page {} &#64;page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt;} div.Section1 {page:Section1;} -->
Java支持的编码格式

三、属性文件

Java中的属性文件只支持 iso-8859-1编码格式,因此,要想在属性文件中保存中文,就必须使用 UCS2编码格式( "uxxxx),因此,出现了很多将这种编码转换成可视编码和工具,如 Eclipse中的一些属性文件编辑插件。

实际上, "uxxxx编码格式在 java C#中都可以使用,如下面的语句所示:

String name= ""u7528"u6237"u540d"u4e0d"u80fd"u4e3a"u7a7a" ;

System.out.println(name);

    上面代码将输出“用户名不能为空”的信息。将 "uxxxx 格式显示成中文非常简单,那么如何将中文还原成 "uxxxxx 格式呢?下面的代码完成了这个工作:
<!-- [if gte mso 9]><xml> Normal 0 7.8 磅 0 2 false false false MicrosoftInternetExplorer4 </xml><![endif]--><!-- [if gte mso 9]><![endif]--><!-- [if !mso]> <style> st1":*{behavior:url(#ieooui) } </style> <![endif]--> <!-- /* Font Definitions */ &#64;font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1;} &#64;font-face {font-family:""&#64;宋体"; panose-1:2 1 6 0 3 1 1 1 1 1;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; font-size:10.5pt; font-family:"Times New Roman";} /* Page Definitions */ &#64;page {} &#64;page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt;} div.Section1 {page:Section1;} -->

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->String ss  =   " 用户名不能为空 " ;
byte [] uncode  =  ss.getBytes( " Unicode " );
int  x  =   0xff ;
String result 
= "" ;
for ( int  i =   2 ; i  <  uncode.length; i ++ )
{
    
if (i  %   2   ==   0 ) result  +=   " \\u " ;
    String abc 
=  Integer.toHexString(x  &  uncode[i]);            
    result 
+=  abc.format( " %2s " , abc).replaceAll( "   " " 0 " );               
}
System.out.println(result);

 

<!-- [if gte mso 9]><xml> Normal 0 7.8 磅 0 2 false false false MicrosoftInternetExplorer4 </xml><![endif]--><!-- [if gte mso 9]><![endif]--><!-- [if !mso]> <style> st1":*{behavior:url(#ieooui) } </style> <![endif]--> <!-- /* Font Definitions */ &#64;font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1;} &#64;font-face {font-family:""&#64;宋体"; panose-1:2 1 6 0 3 1 1 1 1 1;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; font-size:10.5pt; font-family:"Times New Roman";} /* Page Definitions */ &#64;page {} &#64;page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt;} div.Section1 {page:Section1;} --> <!-- [if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable { mso-style-parent:""; font-size:10.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman";} </style> <![endif]-->    上面的代码将输出如下结果:


\u7528\u6237\u540d\u4e0d\u80fd\u4e3a\u7a7a

    好了,现在可以利用这个技术来实现一个属性文件编辑器了。

四、 Web 中的编码问题

    大家碰到最多的编码问题就是在 Web 应用中。先让我们看看下面的程序:

 

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><!--   main.jsp   -->

  
<% @ page language = " java "   pageEncoding = " utf-8 " %>

  
< html >
      
< head >

      
</ head >

      
< body >
          
< form  action ="servlet/MyPost"  method ="post" >
              
< input  type ="text"  name ="user"   />
              
< p />
              
< input  type ="submit"   value ="提交" />
          
</ form >

      
</ body >
  
</ html >


<!-- [if gte mso 9]><xml> Normal 0 7.8 磅 0 2 false false false MicrosoftInternetExplorer4 </xml><![endif]--><!-- [if gte mso 9]><![endif]--> <!-- /* Font Definitions */ &#64;font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1;} &#64;font-face {font-family:""&#64;宋体"; panose-1:2 1 6 0 3 1 1 1 1 1;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; font-size:10.5pt; font-family:"Times New Roman";} /* Page Definitions */ &#64;page {} &#64;page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt;} div.Section1 {page:Section1;} --> <!-- [if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable { mso-style-parent:""; font-size:10.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman";} </style> <![endif]-->    下面是个 Servlet

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->  package servlet;

  import java.io.IOException;
  import java.io.PrintWriter;
  import javax.servlet.ServletException;
  import javax.servlet.http.HttpServlet;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;

  
public   class  MyPost extends HttpServlet
  {

      
public   void  doPost(HttpServletRequest request, HttpServletResponse response)
              throws ServletException, IOException
      {
          String user 
=  request.getParameter( " user " );
          System.
out .println(user);
      }
  }


<!-- [if gte mso 9]><xml> Normal 0 7.8 磅 0 2 false false false MicrosoftInternetExplorer4 </xml><![endif]--><!-- [if gte mso 9]><![endif]--><!-- [if !mso]> <style> st1":*{behavior:url(#ieooui) } </style> <![endif]--> <!-- /* Font Definitions */ &#64;font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1;} &#64;font-face {font-family:""&#64;宋体"; panose-1:2 1 6 0 3 1 1 1 1 1;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; font-size:10.5pt; font-family:"Times New Roman";} /* Page Definitions */ &#64;page {} &#64;page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt;} div.Section1 {page:Section1;} --> <!-- [if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable { mso-style-parent:""; font-size:10.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman";} </style> <![endif]-->

    如果中 main.jsp中输入中文后,向 MyPost提交,在控制台中会输出“ 中 国”,一看就是乱码。如果将 IE的当前编码设成其他的,如由 utf-8改为 gbk,仍然会出现乱码,只是乱得不一样而已。这是因为客户端提交数据时是根据浏览器当前的编码格式来提交的,如浏览器当前为 gbk编码,就以 gbk编码格式来提交。 这本身是不会出现乱码的,问题就出在 Web服务器接收数据的时候, HttpServletRequest在将客户端传来的数据转成 ucs2上出了问题。在默认情况下,是按着 iso-8859-1 编码格式来转的,而这种编码格式并不支持中文,所以也就无法正常显示中文了,解决这个问题的方法是用和客户端浏览器当前编码格式一致的编码来转换,如果是 utf-8,则在 doPost方法中应该用以下的语句来处理:

    request.setCharacterEncoding("utf-8");

    为了对每一个 Servlet都起作用,可以将上面的语句加到 filter里。

    另外,我们一般使用象 MyEclipse 一样的 IDE 来编写 jsp 文件,这样的工具会根据 pageEncoding 属性将 jsp 文件保存成相应的编码格式,但如果要使用象记事本一样的简单的编辑器来编写 jsp 文件,如果 pageEncoding utf-8 ,而在默认时,记事本会将文件保存成 iso-8859-1 ascii )格式,但在 myeclipse 里,如果文件中有中文,它是不允许我们保存成不支持中文的编码格式的,但记事本并不认识 jsp ,因此,这时在 ie 中就无法正确显示出中文了。除非用记事本将其保存在 utf-8 格式。如下图:


 

 



华章培训网视频教程:实现Android版的多功能日历

《Android/OPhone开发完全讲义》(本书版权已输出到台湾)

 样章和目录下载
 
互动网   当当网  卓越亚马逊

《人人都玩开心网:Ext JS+Android+SSH整合开发Web与移动SNS》
 样章下载
 互动网

 乐博Android手机客户端(新浪微博) 发布

<script type="text/javascript"> var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-16915591-1']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); </script>

posted on 2008-07-19 13:45 银河使者 阅读(4556) 评论(16)  编辑  收藏 所属分类: javaweb 原创

<!-- <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/"> <rdf:Description rdf:about="http://www.blogjava.net/nokiaguy/archive/2008/07/19/216024.html" dc:identifier="http://www.blogjava.net/nokiaguy/archive/2008/07/19/216024.html" dc:title="Java编码问题解决方案大揭密" trackback:ping="http://www.blogjava.net/nokiaguy/services/trackbacks/216024.aspx" /> </rdf:RDF> -->

<script type="text/javascript"> //&lt;![CDATA[ Sys.WebForms.PageRequestManager._initialize('AjaxHolder$scriptmanager1', document.getElementById('Form1')); Sys.WebForms.PageRequestManager.getInstance()._updateControls(['tAjaxHolder$UpdatePanel1'], [], [], 90); //]]&gt; </script>

评论

#   re: Java编码问题解决方案大揭密 2008-07-19 14:54 Skywalker

good  回复   更多评论   

#   re: Java编码问题解决方案大揭密 2008-07-19 15:02 BeanSoft

厉害 收藏!  回复   更多评论   

#   re: Java编码问题解决方案大揭密[未登录] 2008-07-19 16:36 James

LZ研究的还不错。不过研究的还是不够深入啊。
说说Web中的情况:
request.setCharacterEncoding("utf-8");这个方法对与Tomcat这样的服务器,有些版本就是不起作用的啦。
还 有个,就是你的jsp例子中的FORM提交,LZ不知道有没有研究过JavaScript中的提交情况,其实你也可以在网页中的charset不是 UTF-8的情况下,将所有传到服务器的内容全部编码成UTF-8的。这个需要用到JavaScript的encodeURIComponent方法,具 体的用法可以GOOGLE一下。
其实关于乱码有更好的解决方法,给大家提个思路:
在客户端将所有的中文全部编码成一种可反编码的编码,比如Unicode的码,用一定的标识符间隔区分,然后在服务器端将接收到的编码过的内容再反编码成实际的内容。这样就可以忽略编码的不同了……  回复   更多评论   

#   re: Java编码问题解决方案大揭密 2008-07-19 16:46 银河使者

@James
不好意思,我的程序都是在tomcat6里调试通过的,再说这些都是servlet规范规定的,所有的web服务器必须遵循。如果某个web服务器不遵循,那么web程序也就无法在其上正常运行了。

web乱码的问题非常多  回复   更多评论   

#   re: Java编码问题解决方案大揭密[未登录] 2008-07-19 16:50 James

LZ可以试验一下Tomcat5,5当中设置request.setCharacterEncoding("utf-8")就是没有效果的。
前段时间一直在搞编码的统一问题,测试过程中遇到的情况。这样设置就没有效果  回复   更多评论   

#   re: Java编码问题解决方案大揭密[未登录] 2008-07-19 16:52 James

补充一个,Servlet是规定了,不过有些服务器在实现这些Servlet的时候就不遵循啊,这让开发人员很是郁闷啊。
比如,response.setCharacterEncoding(String charset);这个方法在有些版本的WebLogic服务器中就没有实现它,结果导致你使用这个方法的话,在某版本的Weblogic服务器中就没有效果,而且会抛Error  回复   更多评论   

#   re: Java编码问题解决方案大揭密 2008-07-19 16:59 银河使者

@James

我的程序是在tomcat6调试通过的,你说的可能是tomcat5以前的版本,但那应该是这些版本的bug,从理论上,是必须支持这个功能的,否则web程序是无法在这些web服务器上运行的。但很遗憾,我没有碰到过这些版本的tomcat。

至于web乱码问题,我只是简单提了一下,本文的目的并不是解决web乱码问题。而是让读者了解java内部编码的问题。如果了解了java编码原理,你认为web乱码问题,甚至其他的乱码问题还能算是问题吗?

你 说的没错,用form提交是产生乱码问题的一种原因,而用httpxmlrequest提交也会产生乱码。这种情况下最好使用encodeURI或 encodeURIComponent将中文编成%xxxx的形式,然后在服务端使用java.net.URLDecoder.decode方法进行解 码。

象在struts里的actionform,都可能会产生乱码问题。

还有就是在http请求头或响应头中传中文,也会出现乱码问题。这些只要了解了java的编码体系,都可以迎刃而解。


最后总结一下:

一般编码传送可以采用两种方式:
1、直接编码。就是采用utf-8、gbk等形式。这样在服务端可以使用setCharacterEncoding指定相应的编码。
2、使用url形式的编码。如%xxxx
如果使用<form>的话,会根据当前浏览器的编码确定发送的中文编码。
如果用javascript,会以utf-8编码发送。  回复   更多评论   

#   re: Java编码问题解决方案大揭密 2008-07-19 17:05 银河使者

如果response.setCharacterEncoding不好使,可以试试response.setContentType("text/html;charset=utf-8");

如果都不好使,就想别的方法,方法还是有的呢,可以用%xxxx形式,或是看一下setCharacterEncoding是怎么弄的,自已处理一下。  回复   更多评论   

#   re: Java编码问题解决方案大揭密 2008-07-19 17:06 银河使者

没有办法,由于做服务器的大多都是老外,它们永远不会有编码问题的,所以估计request.setCharacterEncoding方法就成了可选实现的功能的,但我想国产的web服务器应该都支持,如apusic 。  回复   更多评论   

#   re: Java编码问题解决方案大揭密[未登录] 2008-07-19 17:24 James

@银河使者
你总结的各种编码的原理和过程很不错,对Java的编码也是研究颇多。
只是你说的解决方案不是一个通用的解决之道,要针对不同的情况来区别对待。
下面是我针对你采用的两种方式的一点提醒,希望对看到这篇文章的人有点用
1、 直接编码。服务器端使用setCharacterEncoding指定相应的编码,注意服务器的版本,比如Tomcat5.0版本中就不支持这个方法,设 置后会没有任何效果,使用的时候注意测试一下。如果不行,解决方法之一是换高版本的Tomcat,第二是用编码转换,在Tomcat中的默认流编码是 ISO-8859-1的,只用进行一个转码操作也就可以了。例:String pipeStr = new String(rawStr.getBytes("ISO-8859-1"), "UTF-8");//UTF-8可以改成自己想要的编码
2、如 果代码中拼凑的URL用到中文字符的时候,可以考虑用一个encodeURI或encodeURIComponent,方便服务器端进行统一的UTF-8 解码。如果JavaScript与服务器端进行交互,需要对返回的数据,比如JSON数据进行处理的话,在服务器端需要对返回数据做好编码工作,比如是通 过response写出的,需要加response.setContentType("charset=XXX");来保证返回的数据的编码,使得 JavaScript能够正常解析。另外,如果有JavaScript文件是通过服务器端的Servlet动态生成再传回客户端的话,建议 JavaScript的编码应于客户端的头中的编码一致,不然会出现JavaScript文件中的内容乱码的现象,尽管JavaScript某些时候能正 常使用,但是还是没有乱码的好啊。

PS:银河使者 对编码研究的挺深,有机会可以交流心得……  回复   更多评论   

#   re: Java编码问题解决方案大揭密[未登录] 2008-07-19 17:31 James

现在主流的服务器都是国外的,是苦了我们啊,没办法啊……
国内的服务器做的好的又有几个呢?apusic还可以,可是毕竟力量还是不够强大啊。
大家也就是总结这些东西的使用经验和注意点……  回复   更多评论   

#   re: Java编码问题解决方案大揭密 2008-07-19 18:30 银河使者

@ James
不错,你的第一种方法是比我的通用,因为你的方法是通过String类进行编码转换的,而我的是通过web服务器所提供的 setCharacterEncoding方法实现编码转换的。由于String类是jdk的标准类,所以这种转换方式和web服务器无关,任何基于 java的程序(包括桌面程序)都可以使用这种方式进行转换。
而且将其以ISO-8859-1取出,实际上用iso-8859-1往外取字节,就 相当于是不经过转换,直接取出来了,如将“中国"的utf-8编码“0xe4, 0xb8, 0xad,0xe5,0x9b, 0xbd”直接用iso-8859-1保存在String中(注意,不是将其转换成ucs2,而是直接用utf-8共6个字节将其保存在String 中),代码如下:


byte[] utf8 = new byte[]{(byte)0xe4, (byte)0xb8, (byte)0xad,(byte) 0xe5, (byte)0x9b, (byte)0xbd};
String zg = new String(utf8, "iso-8859-1");
String sss = new String(zg.getBytes("iso-8859-1"), "utf-8"); // 不能用utf-8
String zg1 = new String(sss.getBytes("utf-8"), "utf-8");
System.out.println(sss);
System.out.println(zg1);

其 中 String zg = new String(utf8, "iso-8859-1");的作用就是将“中国”的6个utf-8编码直接保存在String中,在这种情况下,不能使用 zg.getBytes("utf-8")获得字节,因为getBytes方法功能是将String中的ucs2编码(4个字节)转换成utf-8编码的 6个字节,而现在String中是6个字节的utf-8,而不是4个字节的ucs2,如果这时再用utf-8的话,java就会将这6个字节的utf-8 编码当成了3个ucs2编码(2个字节为一个ucs2编码),所以就会出现乱码了。

而用zg.getBytes("iso- 8859-1")就是将这6个字节的utf-8编码按原样取出,然后用 new String(zg.getBytes("iso-8859-1"), "utf-8");将这6个字节按着utf-8格式转换成了java内部使用的ucs2编码。(实际上utf-8编码并没有真正转化为ucs2,因为这样 太占资源了,在程序中还可能有很多英文字符,因此,utf-8就直接放到那了,反正将它转换成ucs也很容易)。

而在sss中的编码就已经是utf-8(ucs2)了,因此,必须使用下面的代码获得字节数组:
sss.getBytes("utf-8")  回复   更多评论   

#   re: Java编码问题解决方案大揭密 2008-07-19 18:41 银河使者

要注意的一点就是getBytes和String都具有编码转换功能。
getBytes是将ucs2转换成其他的编码,而String是将其他的编码转换成ucs2编码  回复   更多评论   

#   re: Java编码问题解决方案大揭密 2008-07-19 18:42 银河使者

如果直接用getBytes("unicode"),就直接把ucs2编码得出来了。

如果用下面的代码:
zg.getBytes("unicode");

由于zg是以iso-8859-1保存的,因此,按着字节输出,就会有下面的结果:

0
e4
0
b8
0
ad
0
e5
0
9b
0
bd

这也说明iso-8859-1的编码转换成ucs2后,第一个字节补0  回复   更多评论   

#   re: Java编码问题解决方案大揭密 2008-07-19 19:13 银河使者

我看到网上关于在servlet中向客户端输出中文字符时乱码解决方案一般是通过如下的代码解决:

response.setCharacterEncoding("utf-8");

response.setContentType("text/html;charset=utf-8");

但关键是web服务器转换字节时是否读取了这个设置的字符集编码呢?如果未读取,等于没设。所以最通用的方法是采用如同的代码解决向客户端中文乱码的问题:

String ss = "中华人民共和国";

String utf8 = new String(ss.getBytes("utf-8"), "iso-8859-1");
response.setCharacterEncoding("iso-8859-1");
response.getWriter().write(utf8);

分享到:
评论

相关推荐

    (转载)用Windows Media 编码器实现现场直播的几点突破

    标题中的“(转载)用Windows Media 编码器实现现场直播的几点突破”指的是通过Windows Media Encoder这一工具来实现高效且稳定的现场直播解决方案。Windows Media Encoder是一款强大的多媒体编码软件,它能够捕获、...

    [转载]彻底解决简繁体软件乱码问题

    总之,解决简繁体软件乱码问题需要理解字符编码、检查和设置操作系统及软件的编码支持,以及利用转换工具。通过学习和实践,可以有效地避免和解决这类问题,提升用户体验。在面对复杂的编码问题时,耐心和细心是关键...

    用UTF-8完全解决JSP+MYSQL多国语言文字编码问题

    此问题这是本人经过数天努力,查遍网上所有此类文章最后自己解决的。转载请务必注明出处

    【转载】解决CHM文件打开无法显示网页的问题 - 耕者 - 博客园.rar

    总之,解决CHM文件打开无法显示网页的问题需要排查多个方面,包括安全设置、文件完整性、编码兼容性和软件版本等。通过尝试上述步骤,大部分情况下都可以成功解决问题。在日常使用中,保持软件更新和注意文件来源的...

    轻松OBS录屏黑屏解决办法(原创文章请勿转载)NVENC Error:init_encoder:报错信息

    虽然“高性能”模式可能会提供更好的性能,但在某些情况下,选择“节能”模式可能有助于解决编码器初始化失败的问题。 完成上述步骤后,关闭并重新启动OBS Studio,通常黑屏问题就会得到解决。如果问题仍然存在,...

    解决网页乱码.zip

    首先,我们来看"jsp,struts,javascript,ajax乱码解决方案(转载)_安装过滤器.txt",这可能是指在Struts框架中使用JavaScript和Ajax进行交互时遇到的乱码问题。在Struts框架中,可以通过设置Filter来统一处理请求和...

    运行vbs脚本报错无效字符、中文乱码的解决方法(编码问题)

    解决此问题的一个方法是确保脚本文件的编码格式被正确识别。在使用文本编辑器编写VBScript时,可以选择以下几种编码格式之一: 1. ANSI编码:这是Windows系统的默认编码格式,通常能够被脚本宿主正确处理,尤其是当...

    js提示框-转载+++ js 乱码+++自动提交+滚动图片加载+箭头导航(转载)

    解决方法包括正确设置页面编码、统一数据传输编码以及在读取或写入字符串时使用合适的编码解码函数。 "自动提交"是指表单的自动提交功能,可以使用JavaScript的事件监听和DOM操作实现。例如,可以监听submit事件,...

    MIME学习笔记--转载

    最初,MIME主要是为了解决1982年RFC 822标准中电子邮件只能使用ASCII字符的局限性,以支持非英语字符、二进制文件(如图片)和附件。随着互联网的发展,MIME已经成为电子邮件的事实标准,并被广泛应用于HTTP协议中。...

    在线广播收听V2009520(转载)

    总结起来,"在线广播收听V2009520(转载)"代表了一种早期的在线广播收听解决方案,具备便携性、兼容性和易用性。它利用了当时的网络技术和音频编码标准,让用户能够跨越地理限制,享受丰富的广播内容。随着技术的发展...

    [转载]迭代算法 1.0

    4. 数据压缩:迭代算法在编码和解码过程中发挥重要作用,例如霍夫曼编码就是迭代构建最优编码树的过程。 5. 操作系统调度:如Linux中的CFS( Completely Fair Scheduler)调度器,使用红黑树和时间片的迭代更新来...

    支持中文的jspsmartupload

    转载 软件说明: 许多朋友反应使用后,出现Bad Version的问题,现在跟大家说明一下,我这个版本编译器是jdk1.6的,所以你们在使用的时候也请选择jdk1.6的编译器,否则会出现bad version的问题。 其他版本: jdk1.4 ...

    字库,字库下载和显示多个汉字和字符.zip

    这里要解决的最大的问题就是要制作一个与汉字内码对应的汉字点阵库,而且还要方便单片机查找。 每个GBK码由两个字节组成,第一个字节为0X81~0XFE,第二字节分为两部分,第一部分是0X40~0X7E,第二部分是0X80~0XFE...

    (转载)关于分辨率,还是没搞清楚

    标题 "(转载)关于分辨率,还是没搞清楚" 暗示了这篇博客可能讨论的是计算机显示技术中的分辨率概念,以及可能存在的误解。在IT领域,分辨率是衡量图像清晰度的关键指标,通常以宽度和高度的像素数表示,如1920x...

    WCF 分布式开发转载

    总之,WCF是一个强大的分布式系统开发工具,它将面向服务的架构理念融入.NET开发,提供了一整套完整的解决方案。通过深入研究`WCFServiceDataContractFormattingFrankXuLei`这个示例,我们可以更好地掌握WCF的核心...

    深入分析 Java I/O 的工作机制(转载)

    Java I/O(输入/输出)系统是Java编程语言中用于处理数据流的重要组成部分,它允许程序与外部资源如文件、网络、硬件设备等进行...在实际项目中,理解并熟练运用这些知识点对于优化程序性能和解决各种I/O问题至关重要。

    转载osgi学习,开发框架

    3. **服务导向**:OSGi支持服务注册和发现,使得组件之间可以通过接口而非硬编码的依赖关系进行通信,降低了耦合度。 4. **版本管理**:OSGi允许同时存在多个版本的相同服务,解决了不同组件间的版本冲突问题,增强...

    【RPA之家转载AA视频教程】14.Configuration .rar

    在这个由RPA之家转载的AA(Automation Anywhere)视频教程中,我们将深入探讨如何在Automation Anywhere A2019版本中处理配置文件,并特别关注如何从XML配置文件中读取节点,以提升自动化效率。 首先,我们要理解...

    Eclipse快捷键大全(转载)

    这篇博客“Eclipse快捷键大全”汇总了Eclipse中的常用快捷键,帮助开发者快速上手并提升编码速度。 在Eclipse中,快捷键可以分为多种类型,包括编辑、导航、搜索、重构和窗口管理等。以下是一些关键的快捷键组合: ...

Global site tag (gtag.js) - Google Analytics