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

简介: 本文为原创,如需转载,请注明作者和出处,谢谢! 一、Java编码是怎么回事? 对于使用中文以及其他非拉丁语系语言的开发人员来说,经常会遇到字符集编码问题。
本文为原创如需转载请注明作者和出处谢谢

一、Java编码是怎么回事

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

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


class  中国
{
    
public  String 雄起()
    {
         
return   " 中国雄起 " ;
    }
}

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

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

class  수퍼맨
{
    
public   void  スーパーマン() {  }
}

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

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

二、Java编码转换

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

    先定义一个字符串变量

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

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

System.out.println(gbk);

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



如果使用下面的语言可以获得“中国”的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编码为2D4EGBK编码为D6D0

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

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

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


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 ]));

 

上面代码的输出结果如下

c7

78

c0

ce

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

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

Java支持的编码格式

三、属性文件

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

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

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

System.out.println(name);

    上面代码将输出“用户名不能为空”的信息。将 "uxxxx 格式显示成中文非常简单那么如何将中文还原成 "uxxxxx 格式呢下面的代码完成了这个工作


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);

 

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


/u7528/u6237/u540d/u4e0d/u80fd/u4e3a/u7a7a

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

四、Web中的编码问题

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

 

<!--   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 >


    下面是个Servlet

  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);
      }
  }


    如果中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 格式。如下图


 

 



国内最棒的Google Android技术社区eoeandroid欢迎访问

《银河系列原创教程》发布

《Java Web开发速学宝典》出版欢迎定购

目录
相关文章
|
10天前
|
Java
Java 字符串分割split空字符串丢失解决方案
Java 字符串分割split空字符串丢失解决方案
|
1月前
|
编解码 Java Apache
Java中文乱码浅析及解决方案
Java中文乱码浅析及解决方案
37 0
|
1月前
|
Java
Java中的异常链:从根源到解决方案
Java中的异常链:从根源到解决方案
35 0
|
1月前
|
搜索推荐 前端开发 Java
Java医院绩效考核系统解决方案源码
作为医院用综合绩效核算系统,系统需要和his系统进行对接,按照设定周期,从his系统获取医院科室和医生、护士、其他人员工作量,对没有录入信息化系统的工作量,绩效考核系统设有手工录入功能(可以批量导入),对获取的数据系统按照设定的公式进行汇算,且设置审核机制,可以退回修正,系统功能强大,完全模拟医院实际绩效核算过程,且每步核算都可以进行调整和参数设置,能适应医院多种绩效核算方式。
41 4
|
2月前
|
监控 安全 物联网
Java基于物联网技术的智慧工地解决方案源代码
应用先进的大数据、物联网、云计算等数字化技术,融合施工运营管理规范和技术标准,建构支撑施工和运营的一体化平台是投资、施工和运营单位能力建设的关键。应用企业架构、设计思维和软件工程方法,深入分析施工和运营技术特性与管理体系,研究开发基于大数据技术的智慧工地信息一体化平台,智慧工地管理平台是依托物联网、互联网建立的大数据管理平台,是一种全新的管理模式,能够实现劳务管理、安全施工、绿色施工的智能化和互联网化。
79 2
|
3月前
|
存储 Java Android开发
IO流:java中解码和编码出现乱码说明及代码实现
IO流:java中解码和编码出现乱码说明及代码实现
|
3月前
|
网络协议 Java Linux
Java 异常 java.net.UnknownHostException 的原因和解决方案
Java 异常 java.net.UnknownHostException 的原因和解决方案
451 0
|
7天前
|
Java API
编码的奇迹:Java 21引入有序集合,数据结构再进化
编码的奇迹:Java 21引入有序集合,数据结构再进化
14 0
|
7天前
|
Java Shell
Java 21颠覆传统:未命名类与实例Main方法的编码变革
Java 21颠覆传统:未命名类与实例Main方法的编码变革
10 0
|
2月前
|
安全 Java 调度
Java中的并发编程挑战与解决方案
【2月更文挑战第5天】在日益复杂的软件开发环境中,Java作为一种广泛应用的编程语言,面临着越来越多的并发编程挑战。本文将探讨Java中常见的并发问题,并提供相应的解决方案,帮助开发人员更好地应对并发编程中的挑战。