Java编程中从乱码中恢复

从乱码中恢复

“乱”主要是因为发生了一次错误的编码转换,所谓恢复,是指要恢复两个关键信息:一个是原来的二进制编码方式A;另一个是错误解读的编码方式B。

恢复的基本思路是尝试进行逆向操作,假定按一种编码转换方式B获取乱码的二进制格式,然后再假定一种编码解读方式A解读这个二进制,查看其看上去的形式,这要尝试多种编码,如果能找到看着正常的字符形式,应该就可以恢复。

这听上去可能比较抽象,我们举个例子来说明,假定乱码形式是“ÀÏÂí”,尝试多种B和A来看字符形式。我们先使用编辑器,以UltraEdit为例,然后使用Java编程来看。

1.使用UltraEdit

UltraEdit支持编码转换和切换查看编码方式,也支持文件的二进制显示和编辑,所以我们以UltraEdit为例,其他一些编辑器可能也有类似功能。

新建一个UTF-8编码的文件,复制“ÀÏÂí”到文件中。使用编码转换,转换到Win-dows-1252编码,执行“文件”→“转换到”→“西欧”→WIN-1252命令。

转换完后,打开十六进制编辑,查看其二进制形式,如图2-4所示。

图2-4 使用UltraEdit查看二进制

可以看出,其形式还是“ÀÏÂí”但二进制格式变成了C0CF C2ED。这个过程相当于假设B是Windows-1252。这个时候,再按照多种编码格式查看这个二进制,在UltraEdit中,关闭十六进制编辑,切换查看编码方式为GB18030,执行“视图”→“查看方式(文件编码)”→“东亚语言”→GB18030命令,切换完后,同样的二进制神奇地变为了正确的字符形式“老马”,打开十六进制编辑器,可以看出二进制还是C0CF C2ED,这个GB18030相当于假设A是GB18030。

这个例子我们碰巧第一次就猜对了。实际中,可能要做多次尝试,过程是类似的,先进行编码转换(使用B编码),然后使用不同编码方式查看(使用A编码),如果能找到看上去对的形式,就恢复了。表2-9列出了主要的B编码格式、对应的二进制,以及按A编码解读的各种形式。

表2-9 尝试不同编码方式进行恢复

可以看出,第一行是正确的,也就是说原来的编码其实是A即GB18030,但被错误解读成了B即Windows-1252了。

2.使用Java

下面我们来看如何使用Java恢复乱码。关于使用Java我们还有很多知识没有介绍,为了完整性起见,本节一并列出相关代码,初学者不明白的可以暂时略过。Java中处理字符串的类有String,String中有我们需要的两个重要方法。

1)public byte[]getBytes(String charsetName),这个方法可以获取一个字符串的给定编码格式的二进制形式。

2)public String(byte bytes[],String charsetName),这个构造方法以给定的二进制数组bytes按照编码格式charsetName解读为一个字符串。

将A看作GB18030,将B看作Windows-1252,进行恢复的Java代码如下所示:

String str = "ÀÏÂí";

String newStr = new String(str.getBytes("windows-1252"),"GB18030");

System.out.println(newStr);

先按照B编码(Windows-1252)获取字符串的二进制,然后按A编码(GB18030)解读这个二进制,得到一个新的字符串,然后输出这个字符串的形式,输出为“老马”。

同样,一次碰巧就对了,实际中,我们可以写一个循环,测试不同的A/B编码中的结果形式,如代码清单2-1所示。

代码清单2-1 恢复乱码的方法

public static void recover(String str)

throws UnsupportedEncodingException{

String[] charsets = new String[]{

"windows-1252","GB18030","Big5","UTF-8"};

for(int i=0;i<charsets.length;i++){

for(int j=0;j<charsets.length;j++){

if(i!=j){

String s = new String(str.getBytes(charsets[i]),charsets[j]);

System.out.println("---- 原来编码(A)假设是: "

+charsets[j]+", 被错误解读为了(B): "+charsets[i]);

System.out.println(s);

System.out.println();

}

}

}

}

以上代码使用不同的编码格式进行测试,如果输出有正确的,那么就可以恢复。

可以看出,恢复的尝试需要进行很多次,上面例子尝试了常见编码GB18030、Windows 1252、Big5、UTF-8共12种组合。这4种编码是常见编码,在大部分实际应用中应该够了。如果有其他编码,可以增加一些尝试。

不是所有的乱码形式都是可以恢复的,如果形式中有很多不能识别的字符(如?),则很难恢复。另外,如果乱码是由于进行了多次解析和转换错误造成的,也很难恢复。

https://www.bilibili.com/video/BV16G4y1Q7Ub/?spm_id_from=333.999.0.0

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值