关于编码的一切【转载】
原文网址:http://pen.defsniky.com/posts/2014-01-16-All-about-encoding.html
乱码与时间格式错误如同矗立在所有程序员面前的太行王屋两座大山。
编码错误或乱码几乎是每个人都会遇到的问题,比如用 Python 抓取网页进行正则分析之后发现在原来网页上正常的文字抓取下来之后变成乱码了,或者是存进 MySQL 之后变成乱码了,又或者本来在编辑器里面编辑得好好的输出之后又是乱码……要命的是每次遇到乱码问题,经过一番痛苦挣扎之后终于解决了,之后总是还会遇到新的乱码问题,这才是真正的“子子孙孙无穷尽也”,本文试图从头到尾将编码问题彻底阐述清楚,至少以后再次遇到烫烫烫烫烫烫烫烫烫
的问题能够有迹可循。
1. 什么是编码
中文 雨
翻译成英文变为 rain
,我们可以说是将中文这种以横竖撇捺等简单笔画为基本元素的编码形式转换成了英文这种以 a-z
26个英文字母为基本元素的编码形式,同样在计算机的世界里面,一切事物都是由 0 和 1 这两个基本元素编码而成的,想象一下显示器上面所呈现出来的所有的精美绝伦的影像以及音响里传出的所有美妙乐章都源自于 0 和 1 这两个简单数字的复杂组合。
编码问题从理论上来说也许并不复杂,只是从一种符号系统到另外一种符号系统之间的映射,但是在实际操作或者实施编码的过程中往往会出现很多问题(见第4部分),我们需要将人类的意图翻译成机器能够理解的二进制编码,在计算机内部经过一系列的加工处理之后,又将这些二进制的信息重新编码成人类可以理解的自然语言(中文或者是英文甚至是图像、影音),对于英文来说,由于其语言构成的规律特性,只需要将其每一个元素(字母或简单符号)与二进制数进行一一对应,然后按照顺序排列就可以得到相应的单词、语句,因而简单的ASCII编码系统已经足够应付,然而为了表示更多的语系或符号,我们就不得不 ASCII编码系统进行扩充,以容纳或者表示更多的语言符号,而乱码的问题也大多产生与此,接下来继续看一下计算机是如何对更多的语言符号进行编码的。
2. 如何编码
很巧的是编码格式与时间格式等问题以及许多计算机相关的问题都避免不了与格式相关,统一的格式源自于相同的规则或者说标准(Standard)。ASCII第一次以规范标准的型态发表是在1967年,最后一次更新则是在1986年,至今为止共定义了128个字符(Wiki),在ASCII编码中每一个字符需要8位来表示,而8位一共可以编码2**8 = 256
个字符,这显然不足以将全世界各种不同语系、各种不同的符号涵盖在内,因而就需要将其进行扩展,也就是我们现在最常用的Unicode,现在 Unicode 仍然在不断增加,每次增加都会有新的字符被编码进来,Unicode目前普遍采用的是UCS-2,它用两个字节来编码一个字符,每个字符占用2个字节,这样理论上一共最多可以表示2**16 = 65536
个字符,其中中文在Unicode表中所对应的二进制数字(转换成十六进制后)的范围是:4E00 - 9FFF
中日韩统一表意文字(CJK Unified Ideographs)。ASCII 与 Unicode 的编码方式就如同 C 语言中 char
类型与 int
类型的区别一样。
3. Unicode 与 UTF-8
Unicode是一种编码标准,比如说它规定汉字雨
对应的数字大小为0x96e8
(十进制38632),因而从本质上来说Unicode只是一张字符表(code table),但是具体用什么方法来实现这种编码的转换,也有许多不同的选择,常见的UTF-8(8-bit Unicode Transformation Format)即是其中一种转换方法。(UTF-8 and Unicode FAQ),其工作方式如下图所示:
4. 实现过程中的各个环节
字符从键盘输入到显示器显示出来,一般会经历下面几个过程:
首先是编码过程,这一过程与所用的编辑器相关,以 vim 为例,当以 ASCII 的格式保存文件时,如果文件中含有 ASCII 字符之外的字符,则在保存的时候就会报错,因而需要将 vim 设置为 UTF-8 的编码格式(以UTF-8的方法保存、读取文件),方法如下:
1 #file ~/.vimrc 2 set fileencoding=utf-8
大多数编辑器中出现乱码的问题多是由于保存格式的原因所导致,因此一般可以通过改变配置中的编码格式(如设为UTF-8)修复。
对程序员来来说更关心的是在特定编程环境下,字符的编码是如何被加工处理的,下面就以 Python 2.7.5 为例加以解释。Python 2.x 中默认的编码格式为 ASCII:
1 import sys 2 sys.getdefaultencoding() 3 //Output >>> 'ascii'
UTF-8的编码方式规定,Unicode范围由U+0800至U+FFFF的字符(如
雨
)使用三个字节进行编码,其编码方式如下:U+00000800 – U+0000FFFF <-> 1110xxxx 10xxxxxx 10xxxxxx
如此一来,我们便知道会出现'\xe9\x9b\xa8'这种奇怪的乱码的原因是什么了:
1 rain = '雨' 2 rain 3 //Output >>> '\xe9\x9b\xa8' 4 5 rain.decode('utf8') 6 //Output >>> u'\u96e8' 7 8 rain.encode('utf8') 9 //Raise error: 10 """ 11 Traceback (most recent call last): 12 File "<stdin>", line 1, in <module> 13 UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in position 0: ordinal not in range(128) 14 """
出现上面编码错误的原因还要从UTF-8的编码方法中找,UTF-8使用3个字节对
雨
字进行编码,得到的Unicode码为应为'\u96e8',而其对应的UTF-8数字却为'e99ba8'(见上面UTF-8的编码方式中的xxxx),而这三个字节在 ASCII 中则被表示为'\xe9\x9b\xa8',因此这一编码重新以UTF-8进行解码rain.decode('utf8')
仍然可以得到正确的Unicode,但是在ASCII环境下进行UTF-8编码则会报错,因为已经超出了ASCII的编码范围。解决这一问题的方法就是设定默认的编码方式为UTF-8:1 import sys 2 reload(sys)'''Python 运行时会检查环境设置并删除setdefaultencoding方法,因而需要reload(sys)''' 3 sys.setdefaultencoding('utf8')
最后一步是关于解码的过程,即将计算机存储的二进制数转换成屏幕上显示出来的各式各样的字符,这一过程中产生的乱码一方面可能是由于系统不支持对某些字体的渲染甚至对于较旧的系统不支持某些特殊字符的显示,另一方面仍然可能是所配置的编码格式的问题,尝试将编码格式设置为UTF-8或许解决问题。
总结
本文试图理清计算机中关于编码的一系列概念,如 ASCII、Unicode、UTF-8等,并试图从编码及解码的各个层面找出可能出现乱码的原因,为以后能够更快地定位乱码错误原因提供参考。
- 版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0
- 原文网址:http://pen.defsniky.com/posts/2014-01-16-All-about-encoding.html
转载于:https://www.cnblogs.com/garner/p/3529056.html
关于编码的一切【转载】相关推荐
- 程序员需要谨记的9个安全编码规则【转载】
历史已经证明,软件设计的缺陷一直是导致其漏洞被利用的最主要的罪魁祸首.安全专家发现,多数漏洞源自常见软件中相对有限的一些漏洞.软件开发者和设计者应当严格检查程序中的各种错误,尽量在软件部署之前就减少或 ...
- android 视频编码vfr cfr,[转载]VFR的源转换CRF输出 批处理
[转载]VFR的源转换CRF输出 批处理 (2017-01-09 20:09:33) http://tieba.baidu.com/p/2469580915 字幕支持vfr(tc) 帧率属于一般情况下 ...
- linux nkf 日文编码转换命令[转载]
对于日语的编码 windows : Shift-JIS Linux : 2.4内核使用EUC编码,2.6内核中使用UTF8编码 检查文件编码 nkf -g filename 通常处理字符编码都使用i ...
- c#编码规范【转载】
一.代码格式 在编写代码的过程中,代码格式方面建议遵守一下规则. (1)通常情况下,代码缩进为4个空格,这是Visual Studio 2005的默认设置. (2)在代码中垂直对齐同一层次的左括号和右 ...
- ivx中字体显示_html-中文字体在CSS中的显示(Unicode编码)(转载)
为了方便需要的朋友快速使用,下表中列出了一些常用中文字体的Unicode编码: 宋体 SimSun \5B8B\4F53 黑体 ...
- UnicodeMath编码教程(转载)
原地址:https://www.cnblogs.com/1024th/p/10393218.html 目录 1. 简介 2. 编码简单数学表达式 2.1 分数 2.2 上标和下标 2.3 空白(空格) ...
- HTML URL 编码参考手册-------转载
一.基础知识点: web浏览器通过URL从WEB服务器请求页面. 在线URL编码解码工具-UrlEncode编码-UrlDecode解码在线工具 二.URL编码作用: 1.URL编码将字符转换为可通过 ...
- ASCII 、GB2312、GBK、GB18030、unicode、UTF-8字符集编码详解(转载)
ASCII字符集编码 ASCII码是7位编码,字符在计算机中以其ASCII码方式表示,其长度为1个字节, 有符号字符型数.编码范围是0x00-0x7F(0~127).ASCII字符集包括英文字母.阿拉 ...
- AAuto解析电话薄 VCF文件ENCODING=QUOTED-PRINTABLE编码解码
2019独角兽企业重金招聘Python工程师标准>>> http://www.oschina.net/question/1438716_143767 <pre class=&q ...
- 基础二(格式化字符串、运算符和编码)
一.Python的输出 (1)纯输出一个字符串或数字 print("Hello World") #输出 Hello World print(34) #输出 34 (2)利用字符串连 ...
最新文章
- 排序算法(一) 冒泡排序
- git commit -amend_最常见的Git错误都有哪些,如何解决它们?
- CPA相关功耗分析(二)
- 为什么我的文章没有被推荐?
- 剪裁tiff影像数据_能看更会用,超擎影像云平台带你轻松玩转海量影像!
- Oracle sqlserver mysql的自增变量设置
- 2018服务器 芯片组,2018最新主板知识详解,详谈DIY(主板篇)
- 《了不起的NodeJS》书籍笔记一
- 刷题笔记(一)《王道计算机考研机试指南2》
- 达梦数据库学习之备份还原
- PHP TOP5开源小程序商城盘点
- 微信openid你了解多少?appid,appsecert又是啥?
- Ludwig Otto Hölder
- OKR目标与关键结果法
- wordpress 调用指定页面内容详解2 get_children()
- 2021年低压电工及低压电工证考试
- java 周几_java根据日期获取周几和获取某段时间内周几的日期
- 7-14 然后是几点(C语言)
- 我对计算机专业的看法及对未来的计划
- 好用的富文本编辑器TinyMCE介绍及使用
热门文章
- laravel框架内置的各种路径帮助函数
- 【第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛】Simone and Graph Coloring
- 【深度学习入门到精通系列】2D Unet3D Unet辨析
- 7-22 堆栈模拟队列 (25 分)
- intel 核显linux驱动程序,10nm来也!Intel 11代核显Linux驱动功能冻结
- python清空字典保留变量方法_python学习day06--02字典增删差改以及字符串的一些方法...
- 网络营销越来越“内卷”,SEO优化时需注意什么细节?
- 网站优化有几个优化因素值得引起注意
- python成员变量和全局变量_python 全局变量和局部变量详解笔记
- python检索地址_35.leetcode题目讲解(Python): 搜索插入位置