新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论Java, J2SE, J2ME, J2EE, 以及Eclipse, NetBeans, JBuilder等Java开发环境,还有JSP, JavaServlet, JavaBean, EJB以及struts, hibernate, spring, webwork2, Java 3D, JOGL等相关技术。
    [返回] 中文XML论坛 - 专业的XML技术讨论区计算机技术与应用『 Java/Eclipse 』 → [转帖]java中文问题详解 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 4195 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: [转帖]java中文问题详解 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     hongjunli 帅哥哟,离线,有人找我吗?魔羯座1978-1-20
      
      
      威望:5
      头衔:为振兴论坛而努力!
      等级:研二(中了一篇WWWC Poster)(版主)
      文章:808
      积分:7964
      门派:IEEE.ORG.CN
      注册:2006/3/9

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给hongjunli发送一个短消息 把hongjunli加入好友 查看hongjunli的个人资料 搜索hongjunli在『 Java/Eclipse 』的所有贴子 引用回复这个贴子 回复这个贴子 查看hongjunli的博客楼主
    发贴心情 [转帖]java中文问题详解


    java中 中文问题详解

    预备知识:
     1.字节和unicode
      Java内核是unicode的,就连class文件也是,但是很多媒体,包括文件/流的保存方式
      是使用字节流的。 因此Java要对这些字节流经行转化。char是unicode的,而byte是字节.
      Java中byte/char互转的函数在sun.io的包中间有。其中ByteToCharConverter类是中调度,
      可以用来告诉你,你用的Convertor。其中两个很常用的静态函数是
       public static ByteToCharConverter getDefault() ;
       public static ByteToCharConverter getConverter(String encoding);
      如果你不指定converter,则系统会自动使用当前的Encoding,GB平台上用GBK,EN平台上用
      8859_1
      
      我们来就一个简单的例子:
         "你"的gb码是:0xC4E3 ,unicode是0x4F60
         你用:
         --encoding="gb2312";
         --byte b[]={(byte)"u00c4",(byte)"u00E3"};
         --convertor=ByteToCharConverter.getConverter(encoding);
         --char [] c=converter.convertAll(b);
         --for(int i=0;i<c.length;c++)
         --{
         -- System.out.println(Integer.toHexString(c[i]));
         --}
         --打印出来是0x4F60
         --但是如果使用8859_1的编码,打印出来是
         --0x00C4,0x00E3
         ----例1
         反过来:
         --encoding="gb2312";
            char c[]={"u4F60"};
            convertor=ByteToCharConverter.getConverter(encoding);
         --byte [] b=converter.convertAll(c);
         --for(int i=0;i<b.length;c++)
         --{
         -- System.out.println(Integer.toHexString(b[i]));
         --}
          --打印出来是:0xC4,0xE3
          ----例2
          --如果用8859_1就是0x3F,?号,表示无法转化      --
          很多中文问题就是从这两个最简单的类派生出来的。而却有很多类  
      不直接支持把Encoding输入,这给我们带来诸多不便。很多程序难得用encoding
      了,直接用default的encoding,这就给我们移植带来了很多困难
      --
      2.UTF-8
      --UTF-8是和Unicode一一对应的,其实现很简单
      --
       -- 7位的Unicode: 0 _ _ _ _ _ _ _
      --11位的Unicode: 1 1 0 _ _ _ _ _ 1 0 _ _ _ _ _ _
      --16位的Unicode: 1 1 1 0 _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _
      --21位的Unicode: 1 1 1 1 0 _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _
      --大多数情况是只使用到16位以下的Unicode:
      --"你"的gb码是:0xC4E3 ,unicode是0x4F60
      --我们还是用上面的例子
      --  --例1:0xC4E3的二进制:
      --  --    1 1 0 0 0 1 0 0 1 1 1 0 0 0 1 1
      --  --    由于只有两位我们按照两位的编码来排,但是我们发现这行不通,
      --  --    因为第7位不是0因此,返回"?"
      --  --   
      --  --例2:0x4F60的二进制:
      --  --    0 1 0 0 1 1 1 1 0 1 1 0 0 0 0 0
      --  --    我们用UTF-8补齐,变成:
      --  --    11100100 10111101 10100000
      --  --    E4--BD-- A0
      --  --    于是返回0xE4,0xBD,0xA0
      --  --
      3.String和byte[]
      --String其实核心是char[],然而要把byte转化成String,必须经过编码。
      --String.length()其实就是char数组的长度,如果使用不同的编码,很可
      --能会错分,造成散字和乱码。
      --例:
      ----byte [] b={(byte)"u00c4",(byte)"u00e3"};
      ----String str=new String(b,encoding);  ----
      ----如果encoding=8859_1,会有两个字,但是encoding=gb2312只有一个字  ----
      --这个问题在处理分页是经常发生
      4.Reader,Writer/InputStream,OutputStream
      --Reader和Writer核心是char,InputStream和OutputStream核心是byte。
      --但是Reader和Writer的主要目的是要把Char读/写InputStream/OutputStream
    --一个reader的例子:
    --文件test.txt只有一个"你"字,0xC4,0xE3--
    --String encoding=;
    --InputStreamReader reader=new InputStreamReader(
    ----new FileInputStream("text.txt"),encoding);
    --char []c=new char[10];
    --int length=reader.read(c);
    --for(int i=0;i<c.length;i++)
    ----System.out.println(c[i]);
      --如果encoding是gb2312,则只有一个字符,如果encoding=8859_1,则有两个字符
      --------
    --
    --
      
       ----
     2.我们要对Java的编译器有所了解:
     --javac -encoding
      我们常常没有用到ENCODING这个参数。其实Encoding这个参数对于跨平台的操作是很重要的。
      如果没有指定Encoding,则按照系统的默认Encoding,gb平台上是gb2312,英文平台上是ISO8859_1。 
     --Java的编译器实际上是调用sun.tools.javac.Main的类,对文件进行编译,这个类 --
     有compile函数中间有一个encoding的变量,-encoding的参数其实直接传给encoding变量。
     编译器就是根据这个变量来读取java文件的,然后把用UTF-8形式编译成class文件。
     一个例子:
     --public void test()
     --{
     ----String str="你";
     ----FileWriter write=new FileWriter("test.txt");
     ----write.write(str);
     ----write.close();
     --}
     ----例3
    --如果用gb2312编译,你会找到E4 BD A0的字段
    --
    --如果用8859_1编译,
    --00C4 00E3的二进制:
    --00000000 11000100 00000000 11100011--
    --因为每个字符都大于7位,因此用11位编码:
    --11000001 10000100 11000011 10100011
    --C1-- 84-- C3--  A3
    --你会找到C1 84 C3 A3 --
        
      但是我们往往忽略掉这个参数,因此这样往往会有跨平台的问题:
      --  例3在中文平台上编译,生成ZhClass
      --  例3在英文平台上编译,输出EnClass
      --1.  ZhClass在中文平台上执行OK,但是在英文平台上不行
      --2.  EnClass在英文平台上执行OK,但是在中文平台上不行
      原因:
     --1.在中文平台上编译后,其实str在运行态的char[]是0x4F60, ----
     --在中文平台上运行,FileWriter的缺省编码是gb2312,因此
     --CharToByteConverter会自动用调用gb2312的converter,把str转化
     --成byte输入到FileOutputStream中,于是0xC4,0xE3放进了文件。
     --但是如果是在英文平台下,CharToByteConverter的缺省值是8859_1,
     --FileWriter会自动调用8859_1去转化str,但是他无法解释,因此他会
     --输出"?" ----
     --2. 在英文平台上编译后,其实str在运行态的char[]是0x00C4 0x00E3, ----
     --在中文平台上运行,中文无法识别,因此会出现??
     --  在英文平台上,0x00C4-->0xC4,0x00E3->0xE3,因此0xC4,0xE3被放进了
     --文件
    ----
    1.对于JSP正文的解释:
    --Tomcat首先看一下你的叶面中有没有"<%@page include的符号。有,则在相同
    --地方设定response.setContentType(..);按照encoding的来读,没有他按照8859_1
    --读取文件,然后用UTF-8写成.java文件,然后用sun.tools.Main去读取这个文件,
    --(当然它使用UTF-8去读),然后编译成class文件
    --setContentType改变的是out的属性,out变量缺省的encoding是8859_1

    2.对Parameter的解释
    --很不幸Parameter只有ISO8859_1的解释,这个质料可以在servlet的实现代码中找到。

    3.对include的解释
    格式的,但是很不幸,由于那个写"org.apache.jasper.compiler.Parser"的人
    在数组JspUtil.ValidAttribute[]忘记加了一个参数:encoding,因此导致不支
    持这种方式。你完全可以编译源代码,加上对encoding的支持


    From : http://tb.blog.csdn.net/TrackBack.aspx?PostId=458018


       收藏   分享  
    顶(0)
      




    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/4/23 23:44:00
     
     falcon2222 帅哥哟,离线,有人找我吗?金牛座1982-5-15
      
      等级:大一(高数修炼中)
      文章:22
      积分:148
      门派:W3CHINA.ORG
      注册:2006/2/18

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给falcon2222发送一个短消息 把falcon2222加入好友 查看falcon2222的个人资料 搜索falcon2222在『 Java/Eclipse 』的所有贴子 引用回复这个贴子 回复这个贴子 查看falcon2222的博客2
    发贴心情 
    缘分啊``谢谢啊``

    ----------------------------------------------
    我行我酷

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/5/6 16:32:00
     
     moto 帅哥哟,离线,有人找我吗?
      
      
      等级:大一新生
      文章:5
      积分:94
      门派:XML.ORG.CN
      注册:2007/5/7

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给moto发送一个短消息 把moto加入好友 查看moto的个人资料 搜索moto在『 Java/Eclipse 』的所有贴子 引用回复这个贴子 回复这个贴子 查看moto的博客3
    发贴心情 
    太好了 !!不愁吃不愁穿的了
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/5/7 12:46:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 Java/Eclipse 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2026/4/14 9:24:44

    本主题贴数3,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    62.500ms