用acsii , unicode,utf-8讨论为什么采用中文编程不行

news2024/12/24 21:04:15

一、背景介绍

很多刚接触计算机的同学,可能会发出一个疑问,为什么不能直接使用中文编程

要了解这个问题,还得从计算机的起源说起!

在计算机软件里面,一切的信息都可以用 1 和 0 来表示(严格说连 0 和 1 都没有,只有开和关),也被称为二进制位,英文简称:bit,音译为“比特”,比特是计算机内存中的最小单位(也称原子单位),在计算机系统中,每 bit 可用 0 或 1 表示数位讯号。

在上篇文章中,我们了解到不管是磁盘还是网络传输,最小的存储单元都是字节。

有的同学可能又会发出疑问,为什么不直接使用比特存储?字节和比特又有什么关系呢

虽然比特是硬件上的最小单元,但是光靠 1 和 0 很难知道是什么意思,比特就好比身体的细胞,由于颗粒度太细,很难知道这个细胞属于哪个地方,于是就有了字节这个概念,字节就好比身体的某个器官,更便于识别。

简单的说,从单位换算角度,一个字节 = 8 个比特

通过这一串的 8 个 1 和 0 的不同排列方式,可以表达出 256 个(2的8次方)不同的意思,这样换算率在当时的美国科学家看来,已经足够表达英文中全部字母大小写及符号加控制符了,也就是下文我们要介绍的 ASCII 字母代码表。

上个世纪 60 年代,为了更好的便于计算机传输字符信息,美国制定了一套字符编码规则,对英语字符与二进制位之间的关系做了统一规定,这编码规则被称为 ASCII 编码(美国标准信息交换码),一直沿用至今。

ASCII 编码一共规定了 128 个字符的编码规则,这 128 个字符形成的集合就叫做ASCII 字符集。

在早期的 ASCII 编码中,规定使用单字节中低位的 7 个比特去编码所有的字符,每个字符占用一个字节的后面7位,最前面的1位统一规定为 0

在这个编码规则下,当你在键盘上输入字母 A,计算机会根据 ASCII 字符代码表,找到对应的十进制码值 65,然后换算成二进制码值 01000001,传输到目的地;接受端收到信号之后,会将二进制码值 01000001 再换算成十进制码值 65,然后再根据字符代码表,将十进制码值 65 解码成字母 A,最后输出到控制台。

由此,整个计算机之间的信息传输交换完成!

在 ASCII 编码中,编号 0~31 是控制字符如换行回车删除等,32~126 是可打印字符,可以通过键盘输入并且能够显示出来,一个英文字符占用一个字节。

对于英语来说,用 128 个符号编码就够了,但是随着计算机的快速发展,用来表示其他语言,128 个符号是远远不够的。

所以当 ASCII 码到欧洲的时候,一些欧洲国家就决定对 ASCII 编码进行适当的 扩展和改造,现有的编码规则维持不变,把字节中闲置的最高位也编入新的符号。比如,法语中的 é 的编码为 130(二进制 10000010 )。这样一来,这些欧洲国家使用的编码体系,可以表示最多 256 个符号,这个编码统称为 EASCII(Extended ASCII)。

但是欧洲的语言体系有个特点:小国家特别多,每个国家可能都有自己的语言体系,语言环境十分复杂。因此即使 EASCII 可以表示 256 个字符,也不能统一欧洲的语言环境。

为了解决上面这个问题,欧洲的工程师们想出了一个折中的方案:在 EASCII 中表示的 256 个字符中,前 128 字符和 ASCII 编码表示的字符完全一样,后 128 个字符每个国家或地区都有自己的编码标准。

比如,130 在法语编码中代表了 é,但是在希伯来语编码中代表字母 Gimel (ג),在俄语编码中又会代表另一个符号。但是不管怎样,所有这些编码方式中,0—127 表示的符号是一样的,不一样的只是 128—255 的这一段。

根据这个规则,就形成了很多子标准:ISO-8859-1、ISO-8859-2、ISO-8859-3、……、ISO-8859-16。这些子标准适用于欧洲不同的国家地区。具体关于 ISO-8859 的标准请参考这个链接地址。

到了亚洲国家,使用的文字符号就更多了,汉字就多达 10 万多个。根据上面的信息,我们知道一个字节最多只能表示 256 种符号,这对于汉字来说肯定是不够的,必须使用多个字节表达一个符号。因此才出现了后面的 GB2312、Unicode 等字符集,简体中文常见的编码方式是 GB2312,使用两个字节表示一个汉字,所以理论上最多可以表示 65536 个符号;而 Unicode 字符集是一个很大的字符集合,最多可以使用 4 个字节来表示一个符号,可以容纳 100 多万个符号。

关于字符集的故事发展,我们在此不过深入的讲解,有兴趣的朋友可以看看这个链接地址!

下面我们重点介绍一下 Unicode 字符集!

二、Unicode 字符集

在上文的信息中,我们了解到不同的国家有不同的字符集,如果通过电子邮件把信息传送到另外一个国家的计算机系统中,看到的可能就不是那个原始发送的字符了,很有可能而是乱码

因为计算机里面并没有真正的字符,字符都是以数字的形式存在的,通过邮件传送一个字符,实际上传送的是这个字符对应的字符编码,同一个数字在不同的国家和地区代表的很可能是不同的符号。

为了解决各个国家和地区之间各自使用不同的本地化字符编码带来的不便,工程师们将全世界所有的符号进行了统一编码,称之为 Unicode,也被称为统一码、万国码

所有字符不再区分国家和地区,都是人类共有的符号,如""字在 Unicode 中不再是 GBK 中的 D6D0,而是在任何地方都是 4e2d,如果所有的计算机系统都使用这种编码方式,那么 4e2d 这个字在任何地方都代表汉字中的""。

需要注意的是,Unicode 只是一个字符集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何编码如何存储。这就造成了两个问题:

  • 问题1:如何才能区别 Unicode 和 ASCII ?计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?

  • 问题2:我们知道,英文字母只用一个字节表示就够了,如果 unicode 统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是 0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这对当时存储器来说,是无法满足的。

为了解决 Unicode 字符集中的一些问题,就出现了 UTF(Unicode Transformation Formats) 系列的编码规则。UTF 编码规则具体规定了 Unicode 字符集中的字符是如何编码的。

下面我们就来看看 UTF 系列编码的具体实现。

三、UTF 编码规则

3.1、UTF-16

早期,Unicode 转换格式规定不管什么字符都使用两个字节表示,两个字节其实就是 16 Bit,所以叫做 UTF-16。

UTF-16 编码非常方便,每两个字节表示一个字符,这个在字符串操作时大大简化了操作,编码效率也比较高,尤其适合在本地磁盘和内存之间操作,可以进行字符和字节之间的快速切换。

但是缺陷也很明显,首先就是一个字符占用两个字节,因为很大一部分字符用一个字节表示就够了,现在需要用两个字节,存储空间放大了一倍;其次在网络之间传输数据,容易因为大小端问题,传输后读取的数据会出现乱码。

3.2、UTF-8

随着互联网的普及,强烈要求出现一种统一的编码方式,为了解决 UTF-16  中的缺陷,基于此又诞生了一种可变长度技术,每个编码区域有不同的字节长度,不同类型的字符可以是由 1~4 个字节组成,这种编码规则我们称为 UTF-8,由 Ken Thompson 于1992年创建,用在网页上可以统一展示页面上的中文英文繁体及其它语言正常显示。

UTF-8 最大的一个特点,就是它是一种变长的编码方式。它使用 1~4 个字节表示一个符号,根据不同的符号而变化字节长度,UTF-8 编码可以容纳 2^21 个字符,总共 200 多万个字符。

UTF-8的编码规则很简单,只有二条:

  • 1.对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 unicode码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的,可以完全兼容过去的编码规则

  • 2.对于 n 字节的符号(n>1),第一个字节的前 n 位都设为1,第 n+1 位设为0,后面字节的前两位一律设为 10。剩下的没有提及的二进制位,全部为这个符号的 unicode 码

对不同范围的字符使用不同长度的编码方式,详细的规则如下,其中字母 x 表示可用编码的二进制位。

比如『汉』这个字的 Unicode 编码是 0x6C49。0x6C49 在 0x0800 ~ 0xFFFF 之间,使用 3 字节模板:1110xxxx 10xxxxxx 10xxxxxx。将 0x6C49 写成二进制是:0110 1100 0100 1001, 用这个比特流依次代替模板中的x,得到:11100110 10110001 10001001。

关于 UTF-8 编码技术更加详细的解说,可以参考这个链接!

四、Java 与字符编码

Java 语言内部使用的是 Unicode 字符集,采用 UTF-16 方式编码字符。

但其实,Java 内部还实现了ASCII、LATIN1、ISO8859-1、UTF-8、GBK 等字符集的编码规则,可以很容易实现这些编码之间的相互转换。

在保证跨平台特性的前提下,也支持了全扩展的本地平台字符集,默认显示输出和键盘输入都是采用的本地编码规则,因此,免不了二者的转化问题。

以 windows 操作系统为例,我们看一个简单的例子!

public static void main(String[] args) throws Exception {
    // 我们采用 GBK 进行编码
    byte b[] = "我们一起来学习 Java 语言".getBytes("GBK");
    File file = new File("encoding.txt");
    OutputStream out = new FileOutputStream(file);
    out.write(b);
    out.close();
}

打开输出的文件,内容如下:

我们一起来学习 Java 语言

正常情况下输出,无编码问题,但是如果改成这样呢

public static void main(String[] args) throws Exception {
    // 我们采用 ISO8859-1 进行编码
    byte b[] = "我们一起来学习 Java 语言".getBytes("ISO8859-1");
    File file = new File("encoding.txt");
    OutputStream out = new FileOutputStream(file);
    out.write(b);
    out.close();
}

输出的文件,内容如下:

?????Java??

乱码问题就出现了!

原因相信大家都知道了,就是字符编码和解码的规则不一样导致的。

Java 中的各个类,对于英文字符的支持都非常好,可以正常地写入文件中,但对于中文字符就未必了!

从 Java 源代码到写入文件正确的内容,要经过 Java 源代码 -> Java 字节码 -> 虚拟机 -> 文件几个步骤,在上述过程中的每一步都必须正确地处理汉字的编码,才能够使最终有我们期望的结果。

其中 Java 源代码 -> Java 字节码这一步骤,Java 编译器 Javac 使用的字符集是系统默认的字符集,比如在中文 Windows 操作系统上就是 GBK,而在 Linux 操作系统上是 ISO8859-1。所以经常有同学发出疑问,自己在本地的 windows 系统上运行的很正常,但是把代码部署到了 Linux 操作系统上编译的类中源文件中的中文字符就出现乱码了。

解决办法就是在编译的时候添加 encoding 参数,并指定对应的编码规则,比如 GBK 或者 UTF-8,这样才能够与平台无关。

如果想要查询 jdk 使用的是哪种编码规则,可以通过如下方式查询:

public static void main(String[] args) {
    System.getProperties().list(System.out);
}

输出的内容比较多,重点看下file.encoding变量值就可以,比如小编当前的电脑显示结果如下:

file.encoding=GBK

表明了 JDK 使用的是 GBK 字符集,当对字符串进行操作时,都做了 Unicode 到 GBK 的转换,既然 JDK 用的 GBK 编码,那么用 ISO8859-1 字符集显示 GBK 编码出来的中文当然是有问题的。

因此在实际使用过程中,推荐大家统一编码规则,比如采用比较通用的 UTF-8 编码规则,可以避免无端的文字乱码问题

五、小结

本文主要围绕计算机进行字符传输时碰到的问题,进行了一次简单的知识梳理总结,内容难免有所遗漏,欢迎网友留言指出!

最近网上有传闻说,采用中文来编程,大家可以试想一下,采用中文来编程会是个什么样的结果?

通过上面的分析,我们可以得出一个结论,那就是采用中文编程,如果没有统一编码规则的情况下,会是个灾难;其次也会增加程序员们的工作难度,因为从字节来看,一个汉字至少等于英文的两个字符,所以使用汉字会更加占内存。

还有一点就是,英文最多也就 26 个字符,比较简单,在所有的计算机上都非常通用,如果换成中文的话,截止目前,中文的符号已经超过 10 万个了,还没有完全收集全,如果换成中文来编程,需要穷举所有的中文字符,以防干扰程序的正常执行,这在目前看来基本弊大于利

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

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

相关文章

mongodb节点一直处于recovering状态问题修复

mongoDB版本:5.0.4 该节点mongod服务日志一直在刷如下日志 {"t":{"$date":"2023-06-19T15:24:50.15608:00"},"s":"I", "c":"REPL", "id":5579708, "ctx":"…

云计算的发展趋势及其对企业的影响

第一章:引言 近年来,云计算在IT行业迅猛发展,成为企业提升业务效率和创新能力的重要工具。通过云计算,企业能够将数据和应用程序存储在云端的服务器上,实现灵活的资源调配和高效的数据管理。本文将探讨云计算的发展趋…

Win11无法连接Win7的打印机解决方法

win11无法连接win7的打印机怎么解决?在日常的办公中,局域网可以实现文件管理,打印机共享文件打印等功能,但是如果两个机器系统各不同的话,可能有的就会提示无法连接,下面就把基本简单的共享设置方法分享给大…

uview的折叠面板和u-tabs的扩展

第一个:首先要安装uview UI框架 (已发布如何安装) 第二个:使用uview 中的折叠面板(Collapse 折叠面板 | uView 2.0 - 全面兼容nvue的uni-app生态框架 - uni-app UI框架) 第三点:明白一个插槽使用…

linux - spin lock实现分析

linux - spin lock实现分析 spinlock1 spinlock的数据结构2 spinlock的接口2.1 spin_lock_init2.2 spin_lock2.3 spin_unlock2.4 spin_lock_irq2.5 spin_unlock_irq2.6 spin_lock_irqsave2.7 spin_unlock_irqrestore2.8 spin_lock_bh2.9 spin_unlock_bh spinlock 1 spinlock的数…

第四十三章 开发Productions - ObjectScript Productions - 使用记录映射器 - 编辑记录映射字段和组合

文章目录 第四十三章 开发Productions - ObjectScript Productions - 使用记录映射器 - 编辑记录映射字段和组合编辑记录映射字段和组合NameDatatypeAnnotationWidth (fixed-width record maps only)RequiredRepeating (delimited record maps only)IgnoreTrailing Data (fixed…

RabbitMQ快速上手(延迟队列)

安装 官网 参考文章: ​ https://blog.csdn.net/miaoye520/article/details/123207661 ​ https://blog.csdn.net/lvoelife/article/details/126658695 安装Erlang,并添加环境变量ERLANG_HOME,命令行运行erl 安装rabbitmq,rab…

Pastebin设计之旅:从零设计网络文本存储系统

项目简介:Pastebin是一个在线的文本存储平台,让用户可以存储和分享代码片段或者其他类型的文本。它支持多种编程和标记语言的语法高亮,用户可以选择让他们的"paste"公开或私有。无需注册就可以使用,但注册用户可以更方便…

森海塞尔重磅推出TC Bars智能音视频一体机, 为中小型协作空间缔造理想解决方案

森海塞尔重磅推出TC Bars智能音视频一体机, 为中小型协作空间缔造理想解决方案 全球音频行业先驱森海塞尔重磅推出首款内置摄像头的可扩展一体化会议设备 德国韦德马克,2023年6月13日——森海塞尔作为先进音频技术的首选,致力于使协作与学习…

力扣 617. 合并二叉树

题目来源: C题解1:使用队列实现层序遍历。基于root1,遇到可覆盖部分,直接将该节点指向对应节点,遇到重复部分,则修改root1该节点相应的值。 /*** Definition for a binary tree node.* struct TreeNode {*…

超市零售数据可视化分析(Plotly 指南)

CSDN 上不能插入 HTML,可以在 GitHub Page 上查看: https://paradiseeee.github.io/2022/07/30/超市零售数据可视化分析/ 项目首次发布于 Kesci 上 – 超市零售数据分析。感兴趣的可以直接上去 Fork 之后自己做。由于上面只能用 Jupyter Notebook&#x…

多旋翼无人机试验系统设计与实现

摘 要 世界的航空业的大门被20世纪莱特兄弟制造的“飞行者一号”开启,直至今日处于飞速发展的阶段。随着时代的进步,各种微电子、微传感、通信技术的飞速发展,让无人机在时代内成为一种新型的空中力量。除了军用方面的多种用途,无…

《Linux操作系统编程》第九章 数据查找和筛选工具 : 了解流编辑器sed和报表生成器awk的简单使用

🌷🍁 博主 libin9iOak带您 Go to New World.✨🍁 🦄 个人主页——libin9iOak的博客🎐 🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~&#x1f33…

uni-app滚动分页 兼容(App 小程序 H5)

因为手机端本身屏幕空间不大 所以大家一般都会选择用滚动分页 首先 我在根目录下创建了一个 api目录 下面创建了一个bookApi.js 其中写了一个请求函数 getBookList 根据当前页 page 和 每页展示多少条 pageSize 获取数据 那么 我的组件代码是这样的 <template><scro…

MacBook Pro Apple M2 Max安装MySQL-8.0.33

文章目录 下载安装程序安装数据库配环境变量查看数据库状态 系统&#xff1a;macOS Ventura 芯片&#xff1a;M2 数据库&#xff1a;MySQL 8.0.33 下载安装程序 官网地址&#xff1a;https://www.mysql.com/ 点击页签“DOWLOADS“后将页面拖到底部&#xff0c;点MySQL Commu…

U盘的文件系统为FAT32才可以同时在苹果电脑和windows电脑中正常使用

文章目录 1.驱动器F中的磁盘未被格式化。想现在格式化吗&#xff1f;2.U盘插到苹果电脑上后无法写入 1.驱动器F中的磁盘未被格式化。想现在格式化吗&#xff1f; 我之前U盘的文件系统为exFAT&#xff0c;插入Windows Server 2003系统的电脑中&#xff0c;打开时弹出上面的提示框…

2023上半年软考系统分析师科目一整理-14

2023上半年软考系统分析师科目一整理-14 计算机系统性能评估中&#xff0c;( A )通常采用加法指令的运算速度来衡量计算机的速度。(D )首先计算出处理部件每个计算单元的有效计算率&#xff0c;再按不同字长加以调整&#xff0c;得出该计算单元的理论性能&#xff0c;所有组成该…

JavaFX学习:Observable Collections(观察集合)

JavaFX中的观察集合&#xff08;Observable Collections&#xff09;继承自Java的集合&#xff08;Collections&#xff09;。Java集合提供了List、Map、Set三种集合接口。JavaFX在Java集合基础上派生出可以监听集合内容变化的三种集合接口。接口如下&#xff1a; ObservableL…

【算法与数据结构】剑指 Offer 05、LeetCode替换空格

文章目录 一、题目二、双指针法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、双指针法 思路分析&#xff1a;这道题使用双指针法就能不用额外的辅助空间。首先计算字符串中的空格数量&#xff0c;然后重设…

函数模板和类模板 知识点总结 C++程序设计与算法笔记总结(七) 北京大学 郭炜

函数模板 交换两个整型变量的值的Swap函数&#xff1a; void Swap(int & x,int & y) { int tmp x; x y; y tmp; } 交换两个double型变量的值的Swap函数: void Swap(double & x,double & y) { double tmp x; x y; y tmp; }用函数模板解决&#xff1a; …