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天

import chardet strs = "bema schwimmfl gel gr÷▀e 0" a = chardet.detect(strs) # windows - 1252 str2 = strs.decode(' windows - 1252 ') str2.encode('utf-8') print str2
今天爬虫运行的时候,发现保存下来的HTML页面偶尔有乱码,访问页面发现页面的字符编码是gb2312,而我用Cpdetector编码识别后的结果是 windows - 1252 ,所以下载的时候按照 windows - 1252 去下载便会出现乱码的情况。 百度了一下发现:国人们往往将gb2312与gbk编码等同,某些已经使用了gbk编码里的字符的,仍然声称内容为gb2312编码。而某些编码识别类对gb2312编
Windows 为了支持英语和西欧字符,自己设计了一个编码,对应的在Code Page号是 1252 ,被称为 Windows 1252 Windows 1252 的设计,是参考了ANSI草案(ANSI Draft)。 而ANSI draft后来发展成为正式的国际标准:ISO 8859-1 即, Windows 1252 是在其成为正式标准ISO 8859-1之前而设计的,因此很容易理解, Windows 1252 和ISO 8859...
var document = new HWPFDocument(formFile.OpenReadStream()); 报' Windows - 1252 ' is not a supported encoding name错误 解决方法 在这段代码上面加入 var ep = CodePagesEncodingProvider.Instance; Enco...
# 【1】BeanFactory BeanFactory 是 Spring 的“心脏”。它就是 Spring IoC 容器的真面目。Spring 使用 BeanFactory 来实例化、配置和管理 Bean。 BeanFactory:是IOC容器的核心接口, 它定义了IOC的基本功能,我们看到它主要定义了getBean方法。getBean方法是IOC容器获取bean对象和引发依赖注入的起点。方法的功能是返回特定的名称的Bean。 BeanFactory 是初始化 Bean 和调用它们生命周期方法的“吃苦
糖℃ᶫᵒᵛᵉᵧₒᵤ: kubectl apply -f 两个yaml文件之后,在ldap namespace中会创建两个pod,ldap的pod持久化了这两个目录:”/etc/ldap/sldap.d” 和 ”/var/lib/ldap” ,这两个目录持久化之后,第一次运行创建pod运行正常,创建用户等新增信息之后,应该会持久化。这时重启一下ldap这个pod就会发现启动失败,无法启动,报错持久化目录,前者为空,后者有数据。持久化配置如下: volumeMounts: - name: ldap-pvc mountPath: /etc/ldap/sldap.d subPath: sldap.d - name: ldap-pvc mountPath: /var/lib/ldap subPath: ldap volumes: - name: ldap-pvc persistentVolumeClaim: claimName: ldap-data apiVersion: v1 kind: PersistentVolumeClaim metadata: name: ldap-data namespace: ldap labels: app: ldap-svc spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: nfs 可能是最详细的LDAP讲解 zou8944: 你给的信息太少了,无法判断 可能是最详细的LDAP讲解 糖℃ᶫᵒᵛᵉᵧₒᵤ: volumes: - name: ldap-config-pvc emptyDir: {} - name: ldap-data-pvc emptyDir: {} 这目录挂载pv 然后重启之后启动不起来,报错目录不为空 可能是最详细的LDAP讲解 zou8944: 如果是跑在本机,就挂一个hostPath;如果是云服务,就挂PV。