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期望将三个字节转换为一个字符。但最后一个字节不符合要求,所以前两个字节被一个�代替。而不是每个字节都被�代替。
GBK与UTF-8编码错误转换后,无法再正确恢复的更多相关文章
- Delphi 编码转换 Unicode gbk big5(使用LCMapString设置区域后,再用API转换)
原文:http://blog.dream4dev.com/article.asp?id=17 function UnicodeEncode(Str: string; CodePage: integer ...
- Lex&Yacc Parser错误发生后再次parser之前恢复初始状态
使用lex yacc 对文件进行parser时,如果文件内容有错,parser报错,然后你修改了文件,再次读入文件进行parser,如果你不是重启程序进行parser,那就需要对做些处理了. &quo ...
- eclipse 解决编译出现GBK或UTF8 编码错误的方法
eclipse由于开源所以支持了比较杂的编码方式,而这些一个工程导入时添加了不少的外来程序,由于不是同一工程一次编码带来了其中含有GBK和 UTF8 UTF16 ASCII等文件编译时就会出现错 ...
- Python_编码错误解决办法 python3 UnicodeEncodeError: 'gbk' codec can't encode character '\xXX' in position XX
先说解决办法:头部加几行代码 import io import sys sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='gb1803 ...
- 关于UTF-8和GBK编码的转换
$oldname=mb_convert_encoding($_POST['oldname'], "GBK" , "UTF-8");//将变量转码为GBK,已知原 ...
- 从Java String实例来理解ANSI、Unicode、BMP、UTF等编码概念
转(http://www.codeceo.com/article/java-string-ansi-unicode-bmp-utf.html#0-tsina-1-10971-397232819ff9a ...
- Code::Blocks开发中的字符串编码错误
刚开始使用Code::Blocks开发Windows中文应用程序的朋友们,如果在代码中使用了中文字符串,编译时可能遇到过Illegal byte sequence或Failure to convert ...
- windows下编译java源文件的编码错误
import java.util.Arrays;public class ArrayAsAReference{ public static void main(String[] args) { int ...
- Python 编码错误的本质原因
转载自:https://foofish.net/python-unicode-error.html 不论你是有着多年经验的 Python 老司机还是刚入门 Python 不久的新贵,你一定遇到过Uni ...
随机推荐
- Python -- 网络编程 -- Socket简单网络通信
Qt如果多线程的话,似乎会出BUG 1.服务端(server.py) import sys, socket, threading import binascii from PyQt4 import Q ...
- linux更改文件权限
chown –Rh cheat:cheat /home/cheat/task/Cheat
- Ruby语言学习系列--String 类函数
函数名称 说明 示例 * 将字符串拷贝N次 “ha”*4 >> “hahahaha” + << concat 连接字符串 “yes” + “no” >& ...
- win10装系统--笔记
U盘安装WIN10时显示 windows无法安装到这个磁盘 选中的磁盘采用GPT分区形式 一.原因分析 win8/win10系统均添加快速启动功能,预装的win8/win10电脑默认都是UEFI引导和 ...
- Qt Model View 框架
Model-View及Qt实现 Model-View-Controller架构最早出现在SmallTalk语言中,至今出现了很多变体. Model是负责维护数据(如管理数据库),View负责显示与用户 ...
- 基于Ionic的移动框架搭建
- FineUI表格、窗体、按钮组及事件
//表格 @(F.Grid().IsFluid(true).CssClass("blockpanel").Title("表格").ShowHeader(true ...
- ubuntu上使用ufw配置管理防火墙
在Linux上使用ufw配置管理防火墙 UFW,即简单防火墙uncomplicated firewall,是一个 Arch Linux.Debian 或 Ubuntu 中管理防火墙规则的前端.UFW ...
- [PHP] 超全局变量$_FILES上传文件
1.$_FILES --超全局变量,HTTP 文件上传变量 通过 HTTP POST 方式上传到当前脚本的项目的数组,PHP 能够接受任何来自符合 RFC-1867 标准的浏览器上传的文件, 上传的过 ...
- 通过SourceTree连接SSL有问题的自建gitlab服务器
我用的是 SourceTree 作为Git客户端的,用它连接一个HTTPS证书过期的自建git服务,会收到下面错误: abort: error: _ssl.c:507: error:14090086: ...