资讯专栏INFORMATION COLUMN

彻底理解编码

leoperfect / 3147人阅读

摘要:只有彻底理解编码,遇到编码问题才知道问题的根源在哪里,并找到对应的解决办法。花一点时间去彻底消化并理解他,长远来看,对以后工作效率的提升是非常值得的。比如中国就制定了等编码规范。

只要涉及编程工作,编码是永远绕不开的问题。只有彻底理解编码,遇到编码问题才知道问题的根源在哪里,并找到对应的解决办法。花一点时间去彻底消化并理解他,长远来看,对以后工作效率的提升是非常值得的。下面是我对编码的一些总结和理解,有不对之处还望指正。

1. 什么是编码?为什么会有编码(可参考这里)?

从根本上来说,计算机只能处理01,也就是说只能处理由0和1组成的一串串数字。让人直接用01数字给计算机下达指令或传输字符显然是很困难的;但其实,早期计算机刚兴起时,那时的程序员就是写好01代码传给机器执行的。

人用自然语言沟通,而计算机只处理01代码。为了人与计算机更友好的交互,有人想了办法,将自然语言的每个字符都用一串01数字串来表示,也就是对每个字符用01串来编码,比如A用0100 0001来表示,这样就可以制定一个字符与01数字串的对应表,也即编码表,人只需要输入自然语言(如:Hello),计算机通过查编码表就可以转换为01串,这样机器就可以理解并处理了。

2. 为什么会有多种编码?

众所周知,世界上第一台计算机是在美国诞生的,因此,第一种编码自然是解决英文和01串的对应关系,这就促生了ASCII编码的出台,ASCII编码表用一个字节(8位)包含大小字母、数字、标点符号以及控制字符。

随着计算机的普及,世界上开始有越来越多的国家使用计算机,然而,每个国家都有自己的一套语言,加起来的字符成千上万。而ASCII最多只能编码256个字符,已经不能满足这么多的需求。于是,各国就制定了自己国家的编码表。比如中国就制定了GB2312、GBK、GB18030等编码规范。每个国家都有自己的一套编码,这就导致同一串01数字可能代表两个国家不同的字符,或者同一个字符A,在两个国家分别用不同的01数字串表示。这就导致不同编码的系统互相传输信息时无法正确识别,比如中国用GBK编码的字符传输给美国的服务器,而美国服务器只有ASCII编码表,这就很糟糕。

于是,Unicode编码出现了。Unicode编码将世界上各个国家所有的字符全部收录进去,每个字符都用唯一的01字符串表示,这样的话就做到了全世界所有字符的统一编码,各个国家传输信息都用Unicode编码,根据Unicode编码表就可以识别了。

常用的编码

ASCII:1个字节,实际使用7位,第8位保留,表示英文字符

ISO-8859-1:1个字节,ASCII的升级版,在ASCII的基础上添加了欧洲国家的字符,不能表示中文,常用于Java服务的网络传输

GB2312:2个字节,收录6763个汉字,只能表示简体字

GBK:GB2312的升级版,1个或2个字节,收录21003个汉字,可以表示简体字和繁体字

Unicode(即UCS):原始的Unicode是定长的4个字节,比如字母A,用Unicode表示需要4个字节,比ASCII多了3个字节,由于这样做太浪费空间,因此经过优化制定了变长表示字符的UTF编码。

UTF-8:用1-6个字节表示所有字符,此处使用变长字节表示,优先使用短字节。

UTF-16:用2、4个字节表示所有字符,此处使用变长字节表示,优先使用短字节。

UTF-32:用4个字节表示。

编码和解码

编码:将字符转为二进制(或unicode)。

解码:将二进制(或unicode)转为字符。

不同编码转换

首先应该知道,内存统一用Unicode编码,编码转换都统一转到Unicode,再从Unicode转为其他编码。比如ISO-8859-1和UTF-8之间转换,流程如下:

先知道字符"u"是用ISO-8859-1编码

获取字符"u"的二进制,java可通过getByte("ISO-8859-1")正确解析出该字符的二进制,也可以用十六进制表示,比如AF8U

根据某种规则,将ISO-8859-1的AF8U转化Unicode,再转化为UTF-8的4E2D

java编译的编码问题(可参考这里):

JDK先检查源文件的编码类型,如果没有指定编码类型则用系统的编码读取源文件,如果指定了编码类型则用指定的编码类型打开源文件。

打开源文件后,在内存中编译为.class文件,此时,.class文件是Unicode编码

将内存中的.class文件存入硬盘,此时,.class文件仍然是Unicode编码

浏览器编码问题

看浏览器使用的是什么编码,则显示的页面就是使用什么编码。

发送post请求时,看浏览器用的什么编码,则发送过去的数据就是用什么编码

一般可以查看headers里ContentType,charset是什么编码

服务器编码问题(可参考这里)

服务器收到请求后,经过正确的编码规则解析,服务器才可以正常识别

服务器发送请求时,经过正确的编码规则编码,浏览器才可以正常显示。浏览器也可以自定义编码去解析

记住: 不管是爬虫获取的,浏览器收到的还是从本地硬盘读取的,都是二进制,选择正确的编码类型,才能把二进制或者说01序列解析为正确的字符。也就是用何种方式解析01数字。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/44106.html

相关文章

  • 彻底理解编码

    摘要:只有彻底理解编码,遇到编码问题才知道问题的根源在哪里,并找到对应的解决办法。花一点时间去彻底消化并理解他,长远来看,对以后工作效率的提升是非常值得的。比如中国就制定了等编码规范。 只要涉及编程工作,编码是永远绕不开的问题。只有彻底理解编码,遇到编码问题才知道问题的根源在哪里,并找到对应的解决办法。花一点时间去彻底消化并理解他,长远来看,对以后工作效率的提升是非常值得的。下面是我对编码的...

    guyan0319 评论0 收藏0
  • JS魔法堂:彻底理解0.1 + 0.2 === 0.30000000000000004的背后

    摘要:也就是说不仅是会产生这种问题,只要是采用的浮点数编码方式来表示浮点数时,则会产生这类问题。到这里我们都理解只要采取的浮点数编码的语言均会出现上述问题,只是它们的标准类库已经为我们提供了解决方案而已。 Brief 一天有个朋友问我JS中计算0.7 * 180怎么会等于125.99999999998,坑也太多了吧!那时我猜测是二进制表示数值时发生round-off error所导致,但并不...

    JerryWangSAP 评论0 收藏0
  • 彻底理解Netty,这一篇文章就够了

    摘要:如果什么事都没得做,它也不会死循环,它会将线程休眠起来,直到下一个事件来了再继续干活,这样的一个线程称之为线程。而请求处理逻辑既可以使用单独的线程池进行处理,也可以跟放在读写线程一块处理。 Netty到底是什么 从HTTP说起 有了Netty,你可以实现自己的HTTP服务器,FTP服务器,UDP服务器,RPC服务器,WebSocket服务器,Redis的Proxy服务器,MySQL的P...

    yy13818512006 评论0 收藏0
  • 面向对象的 JavaScript

    摘要:是完全的面向对象语言,它们通过类的形式组织函数和变量,使之不能脱离对象存在。而在基于原型的面向对象方式中,对象则是依靠构造器利用原型构造出来的。 JavaScript 函数式脚本语言特性以及其看似随意的编写风格,导致长期以来人们对这一门语言的误解,即认为 JavaScript 不是一门面向对象的语言,或者只是部分具备一些面向对象的特征。本文将回归面向对象本意,从对语言感悟的角度阐述为什...

    novo 评论0 收藏0
  • 彻底理解使用JavaScript 将Json数据导出CSV文件

    摘要:前言将数据报表导出,是数据报告展示常用的附带功能。今天我们主要讲的是直接通过前端将数据导出的格式的文件。但其实真正的答案应该是把相应的数据转换成和。若是超过浏览器自身限制的最大长度,会导致下载失败。 前言 将数据报表导出,是web数据报告展示常用的附带功能。通常这种功能都是用后端开发人员编写的。今天我们主要讲的是直接通过前端js将数据导出Excel的CSV格式的文件。 原理 首先在本地...

    jsliang 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<