Java中scanner.next()键盘输入中文乱码以及转码乱码的问题

来源:互联网 发布:网络在线肝病咨询 编辑:程序博客网 时间:2024/05/22 06:43

    在写java代码的时候,遇到中文的乱码经常是我们困扰的问题。

当我们定义:

String  s = "欢迎您光临我的CSDN博客";

    这个字符串s的编码是什么呢?答案是它跟你的文件编码有关系,当你把文件编码设置为UTF-8,那么它就是UTF-8的。

在设置为文件UTF-8后,可以通过:

System.out.println(Charset.defaultCharset());

    来得到默认的编码,这里我们设置后便打印出了“UTF-8”,我们怎么确定这个字符串s就会是UTF-8的编码呢? 看下面的代码:

public class Test {    public static void main(String[] args) {        String s = "欢迎您光临我的CSDN博客";        System.out.println("default charset:" + Charset.defaultCharset());        try {            System.out.println("UTF-8:" + new String(s.getBytes(), "UTF-8"));            System.out.println("GBK:" + new String(s.getBytes(), "GBK"));            System.out.println("ISO-8859-1:"                    + new String(s.getBytes(), "ISO-8859-1"));        } catch (UnsupportedEncodingException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }}

    我们用先得到s的字节,然后重新按照特定编码生成新的字符串。打印如下:

default charset:UTF-8
UTF-8:欢迎您光临我的CSDN博客
GBK:娆㈣繋鎮ㄥ厜涓存垜鐨凜SDN鍗氬
ISO-8859-1:欢迎您光临我的CSDN博客

    可以发现只有编码为UTF-8的才没有乱码。这也就说明了当我们定义string的时候写的中文是跟文件编码有关的。

    而在我们文件编码是UTF-8的时候,用Scanner.next()输入的中文却是乱码了。百度上有人说设置Scanner的编码:

Scanner scanner = new Scanner(System.in,"UTF-8");

    但是测试之后发现没起作用。在我们的windows平台默认用的是gbk的编码,而输入的时候也就是gbk了,和文件的编码是两回事。那么我们可以在输入的时候经过:

new String(s.getBytes("GBK"), Charset.defaultCharset());

    这样就可以吧我们输入的中文字符转换为我们设置的文件编码。所以在键盘输入的中文就不会造成乱码了。当然也可以直接写:

new String(s.getBytes("GBK"),“UTF-8”);

    要注意的就是你要的编码之后的字符串一定要跟你文件编码一样才不会造成乱码。

    另外一个在转码的时候,如果知道字符串是什么编码的话,就得在得到字节数组的时候传入编码,才能够正确的读取到字节数组。

    那么,s.getBytes(“GBK”)和s.getBytes()什么区别?

    什么时候用xxx.getBytes(XXX),什么时候用xxx.getBytes()?

我们来看一下.getBytes()的源码:

public byte[] getBytes() {        return StringCoding.encode(value, 0, value.length);    }

再看StringCoding的encode:

 static byte[] encode(char[] ca, int off, int len) {        String csn = Charset.defaultCharset().name();        try {            // use charset name encode() variant which provides caching.            return encode(csn, ca, off, len);        } catch (UnsupportedEncodingException x) {            warnUnsupportedCharset(csn);        }        try {            return encode("ISO-8859-1", ca, off, len);        } catch (UnsupportedEncodingException x) {            // If this code is hit during VM initialization, MessageUtils is            // the only way we will be able to get any kind of error message.            MessageUtils.err("ISO-8859-1 charset not available: "                             + x.toString());            // If we can not find ISO-8859-1 (a required encoding) then things            // are seriously wrong with the installation.            System.exit(1);            return null;        }    }

    可以看到第一句,String csn = Charset.defaultCharset().name(); 当我们直接用getBytes()的时候会默认使用默认的文件编码来获取字节。

    那么如果你的字符串本身的编码和文件的编码不同的话,这样getBytes()那么就会出错了。

所以答案就是:
    除非我们是知道字符串的编码和文件的一样,而想要转换成其他编码的时候才可以用getBytes(),否则就要用getBytes(String charsetName),才能得到正常的文件编码。

原创粉丝点击