Java中文乱码——2、为何会出现"?"

        Java中文乱码——1、Java编解码基础》讲解了Java编解码的细节,本篇幅具体来解释为什么乱码后中文会变成问号“?”。先看一下下面这个例子。

    public static void main(String[] args) throws UnsupportedEncodingException {
        String s = "GBK中文";
        printCharArr(s.toCharArray());
        byte[] bs = s.getBytes("ISO-8859-1");
        printByteArr(bs);
        String s2 = new String(bs, "GBK");
        printCharArr(s2.toCharArray());
        System.out.println(s2);
    }

    private void printByteArr(byte[] bs) {
        StringBuilder sb = new StringBuilder();
        for(byte b : bs) {
            sb.append(toHex(b)).append(",");
        }
        System.out.println(sb.toString());
    }

    private void printCharArr(char[] charArr) {
        StringBuilder sb = new StringBuilder();
        for(char c : charArr) {
            int high = (c & 0xff00) >> 8;
            int low = c & 0xff;
            sb.append(toHex(high)).append(",");
            sb.append(toHex(low)).append(",");
        }
        System.out.println(sb.toString());
    }

    private String toHex(int intVal) {
        String hex = Integer.toHexString(b);
        if (hex.length() > 2) {
            hex = hex.substring(hex.length() - 2);
        }
        return hex;
    }
    得到了如下输出
0,47,0,42,0,4b,4e,2d,65,87,
47,42,4b,3f,3f,
0,47,0,42,0,4b,0,3f,0,3f,
GBK??
    注意,输出内容是16进制格式的。接着我来详细讲解一下过程。


    字符串“GBK中文”在内存中是以utf-16(unicode)保存的。utf-16为定长编码,每个字符占2字节。如图所示,英文"G"值为0x0047,中文“中”值为0x4e2d。
    bs=s.getBytes("ISO-8859-1")要求将字符串编码成ISO-8859-1,可以理解成将byte[]由utf-16转换成ISO-8859-1。   我们知道,ISO-8859-1也是定长编码,但每个字符只占1个字节。此时英文"G"在ISO-8859-1下有对应的编码,值为0x47。中文“中”在"ISO-8859-1"下没有对应的编码,于是系统默认用问号“?”的ascii值0x3f代替。可以看到,此时已经发生了信息丢失。
    之后,new String(bs, "GBK")要求将bs理解成GBK编码的字符数组,再对数组进行解码,可以理解成将bs由GBK转换成utf-16。我们知道,GBK是变长编码,每个西文字符占1个字节,和ascii兼容,而每个中文占2个字节。对于前三个字符,0x47、0x42、0x4b,在GBK下属于西文的编码范围,因此1次读取1个字节,转换成UTF-16。对于后面2个字符0X3f、0X3f,程序并不知道它们之前是汉字“中”、“文”,只知道它们的编码是0X3f,在GBK下对应西文字符“?“。
    于是,经过如上转换,”GBK中文“变成了”GBK??“。
    那么,发现中文乱码出现"?"以后,是否可以通过转码来恢复呢?
    答案是不能。因为在转换成ISO-8859-1 byte[]的过程中发生了信息丢失,已经无法恢复了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: 如果在Java控制台中出现乱码问题,可以尝试以下几种解决方法。首先,将编码改为UTF-8,这可<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [关于IDEA中Java代码在控制台输出的乱码现象的解决方案。](https://blog.csdn.net/helinjie1245/article/details/125962845)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Java——程序控制台输出时中文乱码](https://blog.csdn.net/b15735105314/article/details/115350162)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Java 入门 之 控制台输出乱码](https://blog.csdn.net/u013630349/article/details/50894491)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值