乱码之一 eclipse console 和 xp console 乱码 全程详解(二)

   乱码的出现,通常是由于我们使用了错误的charset或者与平台相关的charset引起的,java是跨平台的,如果你指定了正确的,或者特定的某种编码,那么在任何时候,它都不会出现我们所不期望的乱码.

在java的io的操作过程中,包括System.out简单输出信息,都是依赖于我们所设置的charset或者默认charset(如果不设置)。

获得系统默认的charset:

import java.nio.charset.Charset;
public class HelloWorld{    
    public static void main(String[]args){
    
                System.out.println("DefaultCharset="+Charset.defaultCharset().name());
                Console console=System.console();
                Field fieldOut=console.getClass().getDeclaredField("out");
                fieldOut.setAccessible(true);
                Object streamEncoder=fieldOut.get(console);
                Field fieldCS=streamEncoder.getClass().getDeclaredField("cs");
                fieldCS.setAccessible(true);
                Charset consoleCharset=(Charset)fieldCS.get(streamEncoder);
                System.out.println("ConsoleCharset="+consoleCharset.name());//x-mswin-936
               System.out.println("===========");
               System.out.println(Charset.defaultCharset().name());
               String chineseChar="汉";
               System.out.println(chineseChar);
    }
}


上面代码的输出在我的电脑上是(java HelloWorld):

DefaultCharset=GBK
ConsoleCharset=x-mswin-936
===========
GBK


说明:ConsoleCharset=x-mswin-936  这种charset是microsoft的中文系统的一种编码了,兼容GBK,所以我们可以认为其就是GBK


数据转换及输出过程解析:

汉(unicode是java在内存中的数据格式)---编码(DefaultCharset=GBK)为二进制--->二进制数据传递----解码(ConsoleCharset=x-mswin-936)-->显示

在这个过程中,有一个编码(encode)的步骤和一个解码(decode)的过程,如果这两个charset不一致,或者不兼容,那么乱码必然出现.


测试方式如下(即更改DefaultCharset为UTF-8,使DefaultCharset与ConsoleCharset不兼容,不一致)

java -Dfile.encoding=UTF-8  HelloWorld

输出为:

DefaultCharset=UTF-8
consoleCharset=x-mswin-936(注:此编码可等同于GBK)
===========
UTF-8
姹 (注:此处为乱码)


好了,乱码就这样子产生了.


回到eclipse我们也可以做类似的测试,不过代码要稍微改一下,因为eclipse的console与xp下面模拟dos的console是不一样的。

上面与Console对象有关的代码不可用。代码如下:


import java.nio.charset.Charset;

public class HelloWorld {
    public static void main(String[] args) {
    System.out.println("DefaultCharset="+Charset.defaultCharset().name());
    String chineseChar="汉";
    System.out.println(chineseChar);
    }
}
输出为:

DefaultCharset=GBK

可能有一些人测试会输出乱码,后面将测试和说明.

eclipse也有console,那么它的console的编码在哪改呢?


就在这个HelloWorld上右键Run As->Run Configuration->Java Application->New->Common->Encoding 即为这个编码了。

我们改为UTF-8再运行上面的代码,输出为:

DefaultCharset=UTF-8

这个地方有点迷惑人的是,当你修改了eclipse的console的Encoding的时候,它在运行一个java application的时候,把Default也改成一样的了

这样子,肯定是不会有乱码的,除非你最初的数据已经是乱码了.

我们可以在Run As->Run Configuration->Java Application上面New的那个选项下的Arguments->VM arguments     输入-Dfile.encoding=GBK


再运行上面的代码,输出将是:

DefaultCharset=GBK
��(乱码)

这下子,如愿以偿的,乱码出现了。

eclipse的console的encoding与xp下dos窗口的作用类似,只是一个输出,它们都有属于自己的编码

在eclipse下如果更改了console的encoding(默认是与项目的编码一致),那么你所运行的这个程序的DefaultCharset也会被更改成与其一致的编码,除非你在vm arguments加入类似-Dfile.encoding=GBK

汉(unicode )---编码(DefaultCharset)为二进制--->二进制数据传递----解码(ConsoleCharset=x-mswin-936)-->console显示


如果对console直接写入字节数组,这个将"汉"字变为数组的过程就是上面的编码过程,而如果我们直接将这个数组写入console,可以同样解决上面的code出现的乱码问题(DefaultCharset=GBK,Console Encoding=UTF-8)

public class HelloWorld {
    public static void main(String[] args) {
    System.out.println("DefaultCharset="+Charset.defaultCharset().name());
    String chineseChar="汉";

  System.out.println(chineseChar);
    System.out.write(chineseChar.getBytes("UTF-8"));

//或者另外的一种写法如下:

    OutputStreamWriter os=new OutputStreamWriter(System.out, "UTF-8");//指定了encode过程中使用的编码
    os.write(chineseChar);
    os.flush();
    }
}

以上代码中,在直接输出乱码的情况下,而后面两种处理方式都可以正确的输出"汉"字

 

在eclipse中运行的程序,如果DefaultCharset 与Console的编码是一致的,并且是可以对你要输出的字符进行编码(对中文,UTF-8和GBK),那么一个字符串是可以直接被输出到Eclipse Console的,如果是乱码,那么也就是说明,保存在String里面的字符已经是乱码或者不是unicode编码的字符串。此时,要分析原字符的乱码产生原因,而不是一味的在System.out进行输出的时候,用各种charset进行试探性输出.



小结:

所有的数据都要依据某种编码转换为二进制存储,传输,再进行解码显示。如果这两个过程所用的charset不一致,就将可能出现乱码(如果是编码兼容,是不会的,如果不兼容,肯定会出现).


下一节,进行文件操作,并进行编码解码的问题,并对与汉字相关的几种编码进行简单的说明。







转载于:https://my.oschina.net/u/186769/blog/659505

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值