如何理解字符编码

一直有个困惑,为什么计算机系统搞那么多字符编码,就一个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,一经查实,立即删除!

相关文章

java bean 验证_Java Bean验证基础

java bean 验证这篇文章总结了一些简单,快速的示例,这些示例说明了您想使用Java Beans Validation API(JSR 349,JSR 303)进行的最常见操作。 记住,Beans Validation独立于Java EE。 尽管它是作为Java EE兼容…

框架下载_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中进行配置相关参数即…

IntelliJ IDEA for Mac 在eclipse(MacOS)模式下的快捷键

文章目录Mac键盘符号eclipse(MacOS)模式下的快捷键General 通用Debugging 调试Search/ Replace 查询/替换Editing 编辑Refactoring 重构Navigation 导航Usage Search 使用查询VCS/ Local History 版本控制/本地历史记录Live Templates 动态代码模板Other 官方文档上没有体现Mac…

java终结器_弃用Java的终结器

java终结器JDK-8165641 (“ Deprecate Object.finalize”)已打开,以“ deprecate Object.finalize() ”,因为“ finalizer本质上存在问题,使用finalizer可能会导致性能问题,死锁&…

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框架&#…

IntelliJ IDEA for Mac 彻底卸载/彻底删除

删除 /Users/liaowenxiong/Library/Logs/目录下所有与 IntelliJ IDEA 相关的文件: cd /Users/liaowenxiong/Library/Logs/ rm -rf *intellij* rm -rf *IntelliJ* rm -rf *JetBrains* rm -rf *jetbrains*删除 /Users/liaowenxiong/Library/Preferences/目录下所有与…

春天猫rtsy_春天重试,因为冬天来了

春天猫rtsy好的,这实际上与冬天无关,众所周知,冬天已经到了 。 它与Spring Retry有关,Spring Retry是一个小的Spring框架库,它使我们可以向应重试的任何任务添加重试功能。 这里有一个很好的教程 ,解释了如…

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

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

python字符串合并去重_015day--python集合和字符串

一、集合关系测试交集: 两个都有 .intersettion() 或用 & 符号差集: 列表a有,列表b没有 .difference() 或用 - 符号并集: 两列表合并,去重 .union() 或用 | 符号合并: .update() 会更改数据…

IntelliJ IDEA for Mac如何存取自定义快捷键配置文件

IntelliJ IDEA for Mac自定义的快捷键配置文件在以下的目录中: /Users/liaowenxiong/library/application support/JetBrains/IntelliJIdea2020.3/keymaps

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

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

linux mysql 分区_Linux :linux磁盘分区(普通分区2T以内),安装免安装版mysql(tar.gz)...

1关闭防火墙:(依次运行 停止-->禁用)Centos7使用firewalld:启动:systemctl start firewalld查看状态:systemctl status firewalld停止:systemctl disable firewalld禁用:systemctl stop firewalld2官网下…

python 3d大数据可视化软件_十大顶级大数据可视化工具推荐

要使数据分析真正有价值和有洞察力,就需要高质量的可视化工具。市场上有很多产品,特点和价格各不相同,本文列出了一些广泛认可的工具。其实企业如何选择一个合适的可视化工具,并不是一件容易的事情,需要仔细的考虑。据…

IntelliJ IDEA 配置文件位置

1 IDEA 2020.1 以上 1.1 Win 语法&#xff1a; %APPDATA%\JetBrains\<product><version>Win上的APPDATA默认位置如下&#xff1a; C:\Users\用户名\AppData\Roaming例子&#xff1a; C:\Users\用户名\AppData\Roaming\JetBrains\IntelliJIdea2020.11.2 MacOS …

mysql 中间表的好处_Mysql中使用中间表提高统计查询速度

对于数据量较大的表&#xff0c;在其上进行统计查询通常会效率很低&#xff0c;并且还要考虑统计查询是否会对在线的应用产生负面影响。通常在这种情况下&#xff0c;使用中间表可以提高统计查询的效率&#xff0c;下面通过对session 表的统计来介绍中间表的使用&#xff1a;(1…

junit 5测试异常处理_使用JUnit 5测试异常

junit 5测试异常处理JUnit 5带来了令人敬畏的改进&#xff0c;并且与以前的版本有很大不同。 JUnit 5在运行时需要Java 8&#xff0c;因此Lambda表达式可以在测试中使用&#xff0c;尤其是在断言中。 这些断言之一非常适合测试异常。 设置项目 为了演示JUnit 5的用法&#xff…

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

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

百度网盘不限速被限速_基本API限速

百度网盘不限速被限速您可能正在开发某种形式的&#xff08;Web / RESTful&#xff09;API&#xff0c;并且如果它是面向公众的&#xff08;甚至是内部的&#xff09;&#xff0c;则通常需要以某种方式对其进行速率限制。 即&#xff0c;限制一段时间内执行的请求数&#xff0c…