FANGYEFENG

Mar 27, 2024

字符编码笔记

虽然一直在舒适地使用着Qt提供的基础类QString,非常的实用,但却一直没有去了解它内部具体是怎么储存字符的。今天查了相关文档,文档上说是用UTF-16去存储字符的,突然感觉我对UTF-16很陌生了,虽然大学时候有专门研究过,但是现在忘得差不多了,今天算是重新复习了一番,记下笔记加深印象。

Unicode是一个符号集,它规定了符号的二进制代码,范围从0x0000~0x10FFFF,比如U+0041表示英文的大写字母A,U+4E25表示汉字。我在网上搜资料看到这样一句话

它并没有规定这个二进制代码应该如何存储

当时有点不太理解,因为我想这不是规定了吗?直接3个字节或者4个字节来存储二进制代码,不就好了吗?
伴随着我的疑问,我读到了UTF-32、UTF-16、UTF-8这样的具体编码实现方式,它们规定了这些编码应该如何去存储,在这里我就不粘贴那些讲解存储方式的图片了。UTF-32其实就跟我上面的想法一样,所有字符采用四个字节来存储,剩余的左边补0就行了,但是这种存储方式对像英文字母、标点符号这种很常用的字符十分的不公平,英文字母和标点符号如果按照ASCII来存储只需要1个字节,但是采用这种的话相当于多了三倍的存储空间,这实在是很难忍受的。因此出现UTF-8、UTF-16这样的编码方式,UTF-8的字符编码跟UTF-32不同,是可变的,从一个字节到四个字节,ASCII的字符的编码方式与UTF-8完全兼容,因此不会出现浪费空间的行为。UTF-16从两个字节到四个字节变动,相比于UTF-32有了很大提升。网络传输的报文基本都是UTF-8来存储的。

还有一点,在像Notepad++这样的编辑器中,常看到UTF-8 BOM、UTF-16 BOM,这个BOM的全程是Byte Order Mark,它其实就是一段文本开头的几个字节,用来表明字节顺序并且可以指示出当前的编码方式。比如像一段UTF-16文本开头两个字节

FE FF

表明是大端编码

FF FE

表明是小端编码
这样解析器才能正确解析,将文本正确的显示出来。UTF-8这样的编码方式没有必要加上BOM,因为不带BOM照样可以解析出来,虽然它也是多字节编码,但它的存储方式注定了它无论是大端还是小端都能正确的解析出来。

OLDER > < NEWER