关于计算机字符编码集合的各个方面问题
一、前言
工作中会时不时遇到一些和字符集有关的问题,此外同事也会问字符集是怎么回事。
个人觉得有必要系统化地整理关于字符集的问题,以便更方便之后的学习和工作。
由于编码本身比较简单,本文不介绍具体某个文字如何使用二进制进行编码。
二、定义
字符集(character set),顾名思义是关于字符的集合,确切地说是关于字符编码的集合=》关于文字、符号的编码集合。
这些字符包括语言字符、少量的图形符号、控制符号(不可见)。
其中语言字符则是显存地球上主流的文字字符,从简单的英文字符、阿拉伯到中文、希腊、拉丁等等。
这些字符集的存在是为了计算机程序服务的。
三、为什么要有
反过来问:如果没有会怎么样?
字符集的在计算机中的作用相当于人类的语言:语言的存在是为了互相能够交流。
字符集的存在,也是为了让不同的程序和不同的数据能够交互。
由于现有计算机的特性--基于二进制计算,所以计算机字符集合人类语言的区别主要在于:前者是对后者的二进制编码
四、发展历史
4.1起源
真实的计算机从美国发源,所以第一个字符集也是美国发明的,称为ASCII码。
4.2图说
4.3几个标准化组织
ISO-International Organization for Standardization 国际标准化组织 1947
IEC-international electrical Commission 国际电气协会 1906
SAC-Standardization Administration of the People's Republic of China 国家标准化管理委员会(原(中国)国家标准总局) 1978,2001
ANSI-American National Standards Institute 美国国家标准委员会 1918
其中电气协会建立一百多年了,而我国的标准组织最迟建立,到现在还不到50年。
4.4名词解释
character set --字符集 ,严格来说,这里应该是字符编码集
bit-比特-指计算中二进制的一位
byte -字节,或者字(word)
bigend(be)--大端,这里特指两个字节编码情况下,编码的高位内容放在内存地址的低位
littleend(le)--小端,这里特指两个字节编码情况下,编码的高位内容放在内存地址的高位
ascii-American Standard Code for Information Interchange,即美国信息交换标准码,说得很直白,就是为了交换用的
GB-guobiao,国家标准的拼音首字母
GB2312-2312号国标
GBK-GBK全称《汉字内码扩展规范》,是国标扩的拼音首字母缩写
GB18030-18030号国标,兼容UCS的汉字编码,分GB18030-2000和GB18030-2005,2022。
UCS-Universal Character Set,全称Universal Multiple-Octet Coded Character Set,中文"统一多字节编码字符集",即统一字符集,ISO标准
Unicode-是Unicode Consortium (UC) 定制的。到现在最新的UNICODE是2022
参考:Unicode – The World Standard for Text and Emoji
BOM-Byte Order Mark,中文名译作“字节顺序标记”.以下内容摘自百度:
在UCS 编码中有一个叫做 "Zero Width No-Break Space" ,中文译名作“零宽无间断间隔”的字符,它的编码是 FEFF。而 FEFF 在 UCS 中是不存在的字符,所以不应该出现在实际传输中。
UCS 规范建议我们在传输字节流前,先传输字符 "Zero Width No-Break Space"。
这样如果接收者收到 FEFF,就表明这个字节流是 Big-Endian 的;
如果收到FFFE,就表明这个字节流是 Little- Endian 的。
因此字符 "Zero Width No-Break Space" (“零宽无间断间隔”)又被称作 BOM。
UTF-8 不需要 BOM 来表明字节顺序,但可以用 BOM 来表明编码方式。字符 "Zero Width No-Break Space" 的 UTF-8 编码是 EF BB BF。所以如果接收者收到以 EF BB BF 开头的字节流,就知道这是 UTF-8编码了。
Windows 就是使用 BOM 来标记文本文件的编码方式的。字符U+FEFF如果出现在字节流的开头,则用来标识该字节流的字节序,是高位在前还是低位在前。如果它出现在字节流的中间,则表达零宽度非换行空格的意义,用户看起来就是一个空格。
从Unicode3.2开始,U+FEFF只能出现在字节流的开头,只能用于标识字节序,就如它的名称——字节序标记——所表示的一样;除此以外的用法已被舍弃。取而代之的是,使用U+2060来表达零宽度无断空白。
类似WINDOWS自带的记事本等软件,在保存一个以UTF-8编码的文件时,会在文件开始的地方插入三个不可见的字符(0xEF 0xBB 0xBF,即BOM)。
它是一串隐藏的字符,用于让记事本等编辑器识别这个文件是否以UTF-8编码。对于一般的文件,这样并不会产生什么麻烦。但对于 PHP来说,BOM是个大麻烦。
PHP并不会忽略BOM,所以在读取、包含或者引用这些文件时,会把BOM作为该文件开头正文的一部分。根据嵌入式语言的特点,这串字符将被直接执行(显示)出来。由此造成即使页面的 top padding 设置为0,也无法让整个网页紧贴浏览器顶部,因为在html一开头有这3个字符呢!
code page-代码页,这里指的是用在windows上的一种编码管理中使用的概念,具体见 https://learn.microsoft.com/en-us/windows/win32/intl/code-page-identifiers
如果是老版本的windows,大家应该相对比较熟悉。
需要注意的是,中文的代码页号为936(gb2313)
utf-8的代码页是 650001。
设置代码页的命令 chcp。
4.5大端好还是小端好
清晰的理解大端和小端_code bean的博客-CSDN博客_windows大小端
大意:没有什么特别好,要因地制宜。
但要记住几点:
Motorola的PowerPC系列CPU采用Big Endian方式存储数据。 Intel的x86系列CPU采用Little Endian方式存储数据。 ARM既可以工作在大端模式,也可以工作在小端模式。在ARM上,我见到的都是用Little Endian方式存储数据。 Windos(x86,x64)和Linux(x86,x64)都是Little Endian操作系统 C/C++语言编写的程序里数据存储顺序是跟编译平台所在的CPU相关的。 JAVA编写的程序则唯一采用Big Endian方式来存储数据。 所有网络协议也都是采用Big Endian的方式来传输数据的。所以有时我们也会把Big Endian方式称之为网络字节序。 ———————————————— 版权声明:本文为CSDN博主「code bean」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/songhuangong123/article/details/125800694
大端就是从左到右的人类阅读习惯-以左为大:1999
五、字符集有关的系统/软件(常见)
5.1windows上的软件
主要针对桌面版本的windows。
notepad --windows 11上允许选择字符集,包括ansi,utf-8,utf8-bom,utf-16-be,utf-16-le。默认会让保存为utf-8编码
notepad++ -默认是utf8编码,可选字符集默认同notepad,但还可以选择目前不那么标准的各国/组织定义的字符集
ie/edge--根据html的指令来显示。但是可以通过浏览器的菜单/指令修改字符集(老版本)
cmd(命令行)-- 可以使用chcp来查看,切换代码页面。
tomcat -web容器,日志默认使用utf-8来输出日志文本.
这种编码的文本无法在cmd下正常显示,需要调整下 logging.properties中编码设置
5.2linux上的软件
linux至少从centos6.x开始,都是默认为UTF字符集合,只不过语言设置稍微有点不同,例如都是zh_CN.UTF-8这样的。
在linux下,部署程序相对会简单一些。
六、字符集的性能问题
如果是英文居多,用UTF-8。如果是中文居多,用UTF-16,节省空间和处理时间。
七、小结
字符集本身不复杂,关键几点:
- 字符集是关于字符的编码集合,用于计算机
- 有多种的字符集
- 现在已经统一到unicode,包括UTF-8,UTF-8 BOM,UTF-16 be,utf-16 le,utf-32
- 乱码是因为处理程序和文本本身不匹配导致,不幸的是为了灵活,处理程序是可以处理各种字符集合,所以有时候反而有点麻烦
- 应该根据应用场景选择是utf-8还是utf-16,而不是一位的使用UTF-8,那是一种偷懒的,甚至有点不负责的做法
- 为了避免混乱,误会,误导,个人建议大家在日常称呼xxx编码更加合理一些,例如UTF-8编码
八、参考
Unicode – The World Standard for Text and Emoji
字符编码的前世今生——一文读懂字符编码 - 腾讯云开发者社区-腾讯云 (tencent.com)
UTF-16BE、UTF-16LE、UTF-16 三者之间的区别_QQxiaoqiang1573的博客-CSDN博客_utf-16le
清晰的理解大端和小端_code bean的博客-CSDN博客_windows大小端