如何理解字符编码

一直有个困惑,为什么计算机系统搞那么多字符编码,就一个Unicode统一天下不就得了,后来看了篇文章,才多少理解一丁点。

英语的国家,只要一个字节就可以表示全部的字符,一个无符合的字节可以表示256个字符,对于英语的国家而言绰绰有余了。但是其它国家的字符就费劲了,如果使用Unicode编码,囊括全部的字符,要统一天下,那么一个字节就远远不够了,需要很多字节来表示一个字符(比如4个字节或者更多字节)才行,因为全球的字符实在TMD太多了。

好了咱们就这么定吧,Unicode编码来表示全部的字符好吗?居然有人反对了,说英文字母只用一个字节表示就够了,如果Unicode统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。总之就是没法达成一致,既然如此,那么就各家自己设计字符编码方案吧,于是乎才有那么一堆UTF-8,GB2312,ISO 8859-1,GBK等等。

但是计算机内存只能保存Unicode编码,这点则是统一的,而且必须统一,否则问题就大了。
如果没有Unicode,会怎么样,举栗子说明下:
中国使用自己的字符集编码GBK对字符串china编码,假设编码后的二进制码就是:0111 0101,那么计算机就按0111 0101存储china。那么美国用户想在他们自己的计算机打开文件查看,就必须使用GBK解码(他们的计算机必须安装GBK编码)才能看到china,这是肯定的。那么这种编码和解码的关系如下图所示:
在这里插入图片描述

计算机是根据GBK编码把中文字符串转换成二进制码后进行存储的,假设GBK编码表如下图所示:
在这里插入图片描述
如上图可以明确知道,字符编码就是规定每个字符对应的二进制码是什么。

文档的内容其实是英文字母,对于美国用户而言他们习惯使用UTF-8字符编码,他们的计算机默认是使用UTF-8编码和解码的,他不希望每次打开这份文档都要指定GBK解码才能正常看内容,那么就必须把这份文档改成UTF-8编码保存才行,这时候问题来了,没有中间码(Unicode),那么怎么把文档的编码改成UTF-8呢?因为字符串china在UTF-8的规则里面,对应的二进制码是1010 0010,如下图所示:

在这里插入图片描述
就是说,计算机是根据GBK的规则把0111 0101转换成字符串china显示给用户看的,也就是说计算机对文档的数据理解就是根据GBK编码规则来理解的。现在要按UTF-8保存文档,就是把china转换成10100010存储,那么01110101如何变成10100010呢?没法变,对吧!所以没有中间码(Unicode)就无法把GBK的文档变成UTF-8的文档。

再举个栗子说明下:
计算机和编程语言都是西方国家发明的,这些计算机对编程语言的理解是基于二进制码,因此计算机对这些二进制码的含义认知应该已经固定和达成统一了,计算机的理解过程用下图简单表示:

int x = 1;
int y = 1;
System.out.println(x + y);

在这里插入图片描述
上面的代码根据计算机本来设计的编码规则理解,可以得到如下图所示的字节码:

在这里插入图片描述
就是说JVM遇到0110,知道是int数据类型,遇到0010知道是=,遇到0111知道是+,所以根据这样的理解,最终计算机知道代码的含义,从而计算得到结果2并且打印输出。

如果计算机没有这样默认的编码规则,那怎么玩?GBK,UTF-8等等这些编码方案都是后面才设计出来的,而且相同的二进制码对应不同的编码方案其含义还完全不同,所以你让系统的指令集如何去理解这些二进制代码。举个比较形象的栗子:好比计算机是个“神人”,中国用户用自己的语言把需求描述清楚了,日本用户用自己的语言也把需求描述清楚了,这两份需求要提交给“神人”去完成,“神人”怎么理解这两份需求呢?你是不是要翻译成“神人”理解的语言才行呀!“神人”只理解Unicode的,所以中国和日本用户必须把需求翻译成Unicode后,“神人”就理解两位用户的需求是啥了,于是“神人”就用自己的能力去完成需求的任务,得到两位用户想要的结果。你如果不要这个“神人”帮忙,想自己完成特定的需求任务可以吗?当然可以,那你自己去创造个“神人”,来理解你的需求就行了。也就是说你自己创造个“机器”,它可以理解你用自己特定的编码规则提交的代码从而完成相应的任务,而且这个“机器”只能理解你的代码,日本用户的代码理解不了,德国的代码也理解不了。这样你觉得满意吗?

所以说计算机必须有个初始的、固定的编码规则,而GBK、UTF-8等编码规则都只是把自己国家的字符所对应的Unicode转换成自己的字符编码而已。如下图所示:

我再举个例子,大家如果理解了就基本ok了,假设浏览器指定字符编码是UTF-8,那我们看看String str = "小妹"的编码是如何变化的:

代码如下:

        String c = "小妹";byte[] bs = c.getBytes("UTF-8"); // ① 使用UTF-8对"小妹"进行编码,得到UTF-8编码String c1 = new String(bs, "ISO-8859-1"); //② 使用ISO-8859-1对UTF-8的编码进行解码,得到错误的Unicode编码byte[] bs1 = c1.getBytes("UNICODE"); // 获取错误的Unicode编码,其实就是字节数组byte[] bs2 = c1.getBytes("ISO-8859-1"); //③ 把错误的Unicode编码,重新转换成原来的UTF-8编码,String c2 = new String(bs2,"UTF-8"); // ④使用UTF-8重新解码得到正确的Unicode编码System.out.println(c2); // ⑤小妹

解读如下:

  1. 字符串“小妹”在内存中的Unicode编码是:11111110 11111111 01011100 00001111 01011001 10111001

  2. 接着浏览器使用UTF-8对“小妹”的Unicode进行编码得到UTF-8编码:11100101 10110000 10001111 11100101 10100110 10111001,接着就传送给了服务器

  3. 服务器默认使用ISO-8859-1解码,得到了错误的Unicode编码:11111110 11111111 00000000 11100101 00000000 10110000 00000000 10001111 00000000 11100101 00000000 10100110 00000000 10111001

  4. 如果想要获得正确的Unicode编码,必须把错误的Unicode编码重新编码成原来的UTF-8编码,因为原来解码是用ISO-8859-1,所以错误的Unicode编码要转换成原来的UTF-8编码,就必须使用ISO-8859-1进行编码才行,得到了UTF-8编码之后,再使用UTF-8重新解码成正确的Unicode编码就可以了。

上述编码的变化过程可以看下图:

在这里插入图片描述

P.S 解码行为就是编码行为,为了区别不同的编码方向和编码含义,所以规定字符从初始编码转换成其它编码叫编码,而从其它编码转换成初始编码叫解码

任何字符在计算机内存中都默认以Unicode编码存在,所以“祖国”这个字符串初始是以Unicode编码存在于内存中的,那么java程序用UTF-8把“祖国”从Unicode(就是字节数组)转换成UTF-8编码(就是字节数组)的过程叫“编码”,java程序再用UTF-8(就是字节数组)将“祖国”从UTF-8编码转换回Unicode编码(就是字节数组)的过程叫“解码”。过程如下图所示:

在这里插入图片描述

通常字符是以某种编码保存在硬盘(磁盘)中,例如GBK,UTF-8,ISO-8859-1等,但是java程序在读取字符到内存时,就必须以Unicode编码存放,换句话说java程序在内存中处理字符的时候,会用到Unicode编码,持久化存储的时候都是以其它编码方案保存。
用图表述如下:
在这里插入图片描述

磁盘文件(假如以UTF-8编码保存)加载至内存,JVM会以UTF-8解码转成Unicode编码。
out.println()写入response,容器会将response中的数据发送给浏览器,这样数据会离开服务器内存一段时间再到用户电脑的内存中,Unicode只在内存中出现,所以写入response也要按某种字符编码(假如也是UTF-8)对文档的数据进行编码后保存,浏览器拿到服务器发送过来的数据后,会以UTF-8解码成Unicode编码,再正常显示出来。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/335091.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

框架下载_25. Scrapy 框架-下载中间件Middleware

1. Spider 下载中间件(Middleware)Spider 中间件(Middleware) 下载器中间件是介入到 Scrapy 的 spider 处理机制的钩子框架,您可以添加代码来处理发送给 Spiders 的 response 及 spider 产生的 item 和 request2. 激活一个下载DOWNLOADER_MIDDLEWARES要激活一个下载…

android activity 显示无焦点_Android面试题集锦之fragemnt

大家可以关注一下小编,小编以后会一直更新Android相关技术资料文章。创建方式静态创建首先我们需要创建一个xml文件,然后创建与之对应的java文件,通过onCreatView()的返回方法进行关联,最后我们需要在Activity中进行配置相关参数即…

node 安装_VUE项目迁移之node.js的安装

【摘要】由于公司的项目需要迁移到VUE中去, 所以就用到了node.js, 这里简单整理了一下node.js的安装教程和环境变量的配置【作者】田鋆鹏Node.js 安装教程1. 在node.js的官网下载安装包下载地址1: https://nodejs.org/en/下载地址2: http://nodejs.cn/直接下载.msi的安装包即可…

jsp mysql servlet_JSP+Servlet+JDBC+mysql实现的学生成绩管理系统

本系统基于JSPServletMysql一个基于JSPServletJdbc的学生成绩管理系统。涉及技术少,易于理解,适合JavaWeb初学者学习使用。难度等级:入门技术栈编辑器Eclipse Version: 2019-12 (4.14.0)前端技术基础:htmlcssJavaScript框架&#…

mariadb mysql 配置文件_MariaDB/MySQL配置文件my.cnf解读

MariaDB/MySQL的默认设置性能非常差,仅仅起一个功能测试的作用,不能用在生产环境中,因此要对一些参数进行调整优化。当然,对配置文件各参数的调整需要根据实际环境,不同时期不同数量级的数据进行性能优化。MySQL/Maria…

react 事件处理_在React中处理事件

react 事件处理在使用React渲染RESTful服务后,我们创建了简单的UI,用于渲染从RESTful服务获取的员工列表。 作为本文的一部分,我们将扩展同一应用程序以支持添加和删除员工操作。 我们将通过添加/删除员工操作来更新react-app后端api&#x…

多元回归求解 机器学习_金融领域里的机器学习算法介绍:人工神经网络

人工智能的发展在很大程度上是由神经网络、深度学习和强化学习推动的。这些复杂的算法可以解决高度复杂的机器学习任务,如图像分类、人脸识别、语音识别和自然语言处理等。这些复杂任务一般是非线性的,同时包含着大量的特征输入。我们下面我们将分几天的…

apache ignite_使用Spring Data的Apache Ignite

apache igniteSpring Data提供了一种统一而简便的方法来访问不同类型的持久性存储,关系数据库系统和NoSQL数据存储。 它位于JPA之上,添加了另一层抽象并定义了基于标准的设计以在Spring上下文中支持持久层。 Apache Ignite IgniteRepository实现了Spri…

java事件处理过程分布写_Java 9中的进程处理

java事件处理过程分布写一直以来,用Java管理操作系统进程都是一项艰巨的任务。 这样做的原因是可用的工具和API较差。 老实说,这并非没有道理:Java并非旨在达到目的。 如果要管理OS进程,则可以使用所需的Shell,Perl脚本…

mac mysql5.7.9 dmg_Mac 安装 mysql5.7

mac 安装msql 5.7最近使用Mac系统,准备搭建一套本地web服务器环境。因为Mac系统没有自带mysql,所以要手动去安装mysql,本次安装mysql最新版5.7.28。安装步骤参考以下博客https://www.jianshu.com/p/71f81a0c62b2安装成功后,因为密…

安卓系统dicom阅读器_用户分享:电子书阅读器Note Pro,一座贴心的移动图书馆...

本文转载自“什么值得买”官网用户“小良读书”,经作者授权转载。Note Pro,一座贴心的移动图书馆移动图书馆貌美的小书郎10.3寸高清大屏更适合专业书籍的阅读如果说多年前入手了一台kindle paperwite3电纸书阅读器,它让我畅游了书籍的江河&am…

vim 编辑器命令整理

文章目录一、基本使用流程二、普通命令模式(一)切换到插入模式(编辑/写入/输入)(二)切换到可视模式(选择文本模式)(三)切换至底行命令模式(四&…

activiti dmn_端到端BPM(带有DMN标记)

activiti dmn下周的红帽峰会即将成为有史以来最好的峰会之一! 而且,如果您是Drools或jBPM的狂热者,您会很忙 :Signavio和Red Hat之间的合作伙伴关系是我们为您准备的另一个顶级演讲。 邓肯道尔(Duncan Doyle&#xff…

netbeans 9_NetBeans 9抢先体验

netbeans 9Java 9即将来临,NetBeans 9也即将来临。在本文中,我们将看到NetBeans 9 Early Access为开发人员提供的支持,以帮助他们构建Java 9兼容的应用程序。 Java 9提供了许多(大约90种) 新功能,包括模块…

同一个ip能否两次加入组播_组播IGMPv1/v2/v3精华知识汇总

闲言少叙,直奔主题,开说之前先做点铺垫,回顾一下网络的基础知识。D类地址划分回顾组播是IPv4地址分类中的D类,我们回顾一下IPv4的地址划分A类:首bit0,0-127网段,网络掩码8,其中0.0.0…

弹窗要打开或保存来自_如何让 PopClip 支持印象笔记客户端:保存到印象笔记amp;高亮文字...

自从印象笔记品牌独立并发布新APP后,Mac系统下很多工具不再支持与印象笔记客户端进行联动,PopClip 就是其中之一。目前 Popclip 官方并未将印象笔记加入到插件的支持中,不过我们可以手动修改来解决这个问题。Popclip 之所以不支持新版本的印象…

vue 混入对象_特性和混入不是面向对象的

vue 混入对象让我立刻说,我们将在这里讨论的功能是那些迫切需要进行放线手术的人带给面向对象编程的纯粹的毒药 ,就像David West在他的《 Object Thinking》一书中所建议的那样。 这些功能具有不同的名称,但是最常见的是traits和mixins 。 我…

glup node 内存不够_Redis:内存被我用完了!该怎么办?

介绍Redis是一个内存数据库,当Redis使用的内存超过物理内存的限制后,内存数据会和磁盘产生频繁的交换,交换会导致Redis性能急剧下降。所以在生产环境中我们通过配置参数maxmemoey来限制使用的内存大小。当实际使用的内存超过maxmemoey后&…

pytest框架_Python最火的第三方开源测试框架——pytest

一、介绍本篇文章是介绍的是Python 世界中最火的第三方单元测试框架:pytest。它有如下主要特性:assert 断言失败时输出详细信息(再也不用去记忆 self.assert* 名称了)自动发现测试模块和函数模块化夹具用以管理各类测试资源对 unittest 完全兼容&#xf…

jvm jstat_使用jstat的JVM统计信息

jvm jstat过去,我已经写过关于Oracle和/或OpenJDK Java开发工具包(JDK)附带的几个命令行工具的信息,但是我从来没有专门写过jstat工具 。 Oracle JDK 9文档Early Access指出jstat用于“监视Java虚拟机(JVM)…