zoukankan      html  css  js  c++  java
  • java的编码问题详解

    ucenter的中文问题终于解决,这也暴露我对Java编码知识的严重不足,经过多次试验和搜索,对这块知识终于有了一个新的认识,所以把理解的内容写道这里

    1:JVM的内存中字符串的编码格式是统一的吗?

    JVM里面的任何字符串资源都是Unicode,String相当于 char[] 。 而JVM中的byte[]是带编码的,比如,Big5,GBK,GB2312,UTF-8之类的。一个GBK编码的byte[] 转换成 String,

    其实就是从GBK编码向Unicode编码转换。一个String转换成一个Big5编码的byte[],其实就是从Unicode编码向Big5编码转换。所以,Unicode是所有编码转换的中间介质。所有的编码都有一个转换器可以转换到Unicode,而Unicode也可以转换到其他所有的编码。

    这个做个测试

    public class CodeTest {
    
        @Test
        public void test() throws UnsupportedEncodingException {
            String str="I am 高兴";
            System.out.println(str);
        }
    }

    在debug中显示'高'的值我39640,为该中文字符的unicode的编码,Java中的char是2个字节的。 

    2:源文件的编码对编译的影响。

    这里我专门使用了Javac和Java两个命令来做个这个试验,源码如下:

    public class CodeTest
    {
    public static void main (String[] args)
    {
    String str="高兴";
    System.out.println(str);
    }
    }

    这个源码我在UE里面把他转成GBK的,编译没有问题。但是转成UTF-8格式,就出现了问题:”楂樺叴“ ,

    public class CodeTest {
    
        @Test
        public void test() throws UnsupportedEncodingException {
    //        String str="I am 君山";
    //        System.out.println(str);
            String str="高兴";
            str=new String(str.getBytes("UTF-8"),"GBK");
            System.out.println(str);
        }
    }

    str的值为”楂樺叴“。说明源文件的编码对编译时有影响的。GBK为本地系统的编码。Javac在编译过程中把UTF-8的转成了GBK.  下面一段是解释:

     Java编译器在对源文件编译前,首先会源文件转换为unicode编码,然后再进行编译。例如:我们的源文件是以UTF-8的方式保存的,而在编译时编译器却把它当作是用GBK方式保存的,这样编译器就会按照GBK->Unicode的编码转换方法对源文件进行转换,然后再编译,这样当然会出错,实际上编译器应当按照UTF-8->Unicode的编码转换方法来对源文件进行转换。 

    常我们手动建立一个java文件Demo.java,并保存。此时Demo.java文件的编码为ANSI,中文操作系统下就是GBK.然后使用javac命令来编译该源文件。”javac Demo.java”。Javac也需要读取java文件,那么javac是使用什么编码来解码我们读取的字节呢?其实javac采用了操作系统默认的GBK编码解码我们读取的字节,这个编码正好也是Demo.java文件的编码,二者一致,所以不会出现乱码情况。让我们来做点手脚,在保存Demo.java文件时,我们选择UTF-8保存。此时Demo.java文件编码就是UTF-8了。我们再使用”javac Demo.java”来编译,如果Demo.java里含有中文字符,此时控制台会出现警告信息,也出现了乱码。究其原因,就是因为javac采用了GBK编码解码我们读取的字节。因为我们的字节是UTF-8编码的,所以会出现乱码。如果不信的话你可以自己试试。那么解决办法呢?解决办法就是使用javac的encoding参数来制定我们的解码编码。如下:javac -encoding UTF-8 Demo.java。这里我们指定了使用UTF-8来解码读取的字节,由于这个编码和Demo.java文件编码一致,所以不会出现乱码情况了。

    3:String的编码和解码

    String对象的getBytes()可以对字符串进行编码转化成byte数组。

     public static void encode() {  
            String name = "I am 君山"; 
            toHex(name.toCharArray()); 
            try { 
                byte[] iso8859 = name.getBytes("ISO-8859-1"); 
                toHex(iso8859); 
                byte[] gb2312 = name.getBytes("GB2312"); 
                toHex(gb2312); 
                byte[] gbk = name.getBytes("GBK"); 
                toHex(gbk); 
                byte[] utf16 = name.getBytes("UTF-16"); 
                toHex(utf16); 
                byte[] utf8 = name.getBytes("UTF-8"); 
                toHex(utf8); 
            } catch (UnsupportedEncodingException e) { 
                e.printStackTrace(); 
            } 
     }

    默认使用系统编码。

    String(byte[],charset)这是对字节数组进行解码。这个是经常容易出问题的地方,你使用gbk编码,却使用utf-8解码,那么生成的String的unicode的编码已经变了。字节数组通过编码映射到指定的字符,然后这些字符转成unicode编码转成

    解码的黑洞问题:

    将中文和中文符号经过不支持中文的 ISO-8859-1 编码后,所有字符变成了“?”,这是因为用 ISO-8859-1 进行编解码时遇到不在码值范围内的字符时统一用 3f 表示,这也就是通常所说的“黑洞”,所有 ISO-8859-1 不认识的字符都变成了“?”。

  • 相关阅读:
    noi 2011 noi嘉年华 动态规划
    最小乘积生成树
    noi 2009 二叉查找树 动态规划
    noi 2010 超级钢琴 划分树
    noi 2011 阿狸的打字机 AC自动机
    noi 2009 变换序列 贪心
    poj 3659 Cell Phone Network 动态规划
    noi 2010 航空管制 贪心
    IDEA14下配置SVN
    在SpringMVC框架下建立Web项目时web.xml到底该写些什么呢?
  • 原文地址:https://www.cnblogs.com/gaoxing/p/4372638.html
Copyright © 2011-2022 走看看