zoukankan      html  css  js  c++  java
  • GBK与UTF-8编码错误转换后,无法再正确恢复

    字符集错误转换导致的问题

    UTF-8格式编码的字节流,按GBK字符集转换为字符串,会出现乱码,这很正常。但将其重新转为字节流,再用UTF-8字符集转为字符串,还是乱码。这就让我产生了疑惑,虽然使用错误的字符集必然导致乱码,但字节的信息并没有改变,因此再转为字节流,用正确的字符集解码,应该得到正常的字符串。但事实是,被错误字符集转换过的字符串,无法恢复到原来的字符集。

    问题的根本原因

    造成该问题的根源是字节发生了变化。GBK或UTF-8遇到无法解析的字符时,会使用特殊的字符代替,因此造成原有字节信息的丢失,无法恢复。

    错误转换的分析

    UTF-8 → GBK

    对于一串UTF-8编码的字节流,使用GBK进行解码。连续两个大于127的字节被认为是一个GBK编码的字符;若只读到一个大于127的字节,便发生错误,无法解析。此时,用字符'?'代替错误字节,ASCII码是63。
    “樊”字为例,UTF-8编码使用三个字节表示该字符,字节码为[11100110, 10101000, 10001010]([e6, a8, 8a])。使用GBK解码时,读到第一个字节大于127,则取两个字节解析为一个GBK字符。前两个字节e6 8a被解析为GBK字符——妯。 第三个字节无法解析,所以赋值为?,最后的结果是 妯?
    可以看出,最后一个字节的信息丢失了,由8a变成3F,即使把结果再转换为字节流,也无法用utf-8字符集正确解析了。

    GBK → UTF-8

    对于一串GBK编码的字节流,使用UTF-8解码。UTF-8对于字节的格式有严格要求,当解析某个字符失败时,使用'�'(UTF-8编码为EF BF BD)代替。
    继续以“樊”字为例,其GBK字节码为[10110111, 10101110]([B7, AE])。使用UTF-8解码时,根据规则,要求10开头的字节之前,必须有字节标识一个字符的长度,所以两个字节都无法解析。最后的字符串是��。
    可以看出,所有的字节信息都丢失了,因此无法再使用GBK解析该字符串。
    注意,UTF-8用�替换,是以字符为单位的。例如[11100110, 10101000, 01000001]使用UTF-8解码,得到的结果是�A,而不是��A。根据第一个字节的格式,UTF-8期望将三个字节转换为一个字符。但最后一个字节不符合要求,所以前两个字节被一个�代替。而不是每个字节都被�代替。

  • 相关阅读:
    JAVA学习日记1-0706
    同步一个fork
    面试题 17.13. 恢复空格-7月9日
    3. 无重复字符的最长子串(leetcode)-7月8日
    面试题 16.11. 跳水板(leetcode)-7月8日
    112.路径总和(leetcode)-7月7日
    Git使用入门
    第一次尝试
    OpenPCDet: Open-MMLab 面向LiDAR点云表征的3D目标检测代码库
    人工智能和机器学习能为抗击新冠肺炎做些什么?
  • 原文地址:https://www.cnblogs.com/DataArt/p/10010878.html
Copyright © 2011-2022 走看看