Windows-1252字符集(MS1252)造成的困扰

Windows-1252字符集造成的困扰

ISO8859-1与MS1252的差别

Windows-1252字符集是ISO8859-1的超集,与ISO8859-1的唯一不同点在于0x80-0x9F这两页,差别如下图:
ISO8859-1
Windows-1252
注意看两张图的中间,ISO8859-1为空,而Windows-1252有内容,但是0x81,0x8D,0x8F,0x90,0x9D这几个地方是空的,且被标识为不可填充。

MS1252带来的问题

这样会造成的问题是,当一个字节数组被指定使用Windows-1252解码时,字节数组中的0x81,0x8D,0x8F,0x90,0x9D会被转换为?(0x3f),如果你是从网络中接收到的采用UTF-8编码的字节数组,在本地接收并采用Windows-1252解码,如果接收到的字节数组恰好包含上述几个字节,那么我们就没有办法采用Windows-1252解码 - UTF-8编码的方式还原接收到的信息,因为相应字节被永久破坏掉了。
会被转换的字节
如下代码模拟了这一现象。

    String str = new String("华侨永亨银行");
    // 采用UTF-8编码得到字节数组
    byte[] bytes = str.getBytes("UTF-8");
    // bytes: {e5 8d 8e e4 be a8 e6 b0 b8 e4 ba a8 e9 93 b6 e8 a1 8c}
    // 注意第二个字节0x8d,在下面的编解码中被自动转换成了3f

    // 采用Windows-1252解码得到字符串
    str = new String(bytes, "Windows-1252");
    // 采用windows-1252编码,还原字节数组
    bytes = str.getBytes("Windows-1252");
    // bytes: {e5 3f 8e e4 be a8 e6 b0 b8 e4 ba a8 e9 93 b6 e8 a1 8c}

    // 采用UTF-8解码,预期得到原字符串
    str = new String(bytes, "UTF-8");
    // str: ???侨永亨银行,第一个字被永久性破坏

同理也可证明含有另外几个字节0x81,0x8F,0x90,0x9D的字符串也会被破坏。

解决方案

当确定传入的字节中含有上述几个特定的字节时,应该使用ISO8859-1进行接收,当然最后直接使用最终字符集(如这里的UTF-8)。通过实际测试很容易知道,ISO8859-1,没有Windows-1252的情况。

我遇到的情景

采用https协议与服务端进行通讯,按照默认字符集进行接收(默认Windows-1252),由于这是很久以前系统中已经写好的程序,且使用了很久也没有出现问题,恰巧我的需求是接收中文,因此采用的方案是:先按照默认字符集进行接收,拿到字符串后截取指定位置的字符串,按照默认字符集编码成byte,再按照UTF-8解码成中文字符串,解析结果总是会有几个汉字出现乱码的问题。逐步排查才发现有字节被永久性破坏。排查耗时:0.5天

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值