writeline

计算机只能识别0和1,任何数据格式,包括数字、文本、图像、音乐、视频等等,都表示为一串由0和1组成的二进制数据。如何将一串二进制数据识别为有意义的数据类型,这是一个软件问题,一种格式,一种约定。

ASCII编码

现代计算机的软件和硬件设计最初是由一群以英语为母语的人设计的。英文只有52个字母(区分大小写),加上一些常用的标点符号和控制符号(比如换行和回车),大概是100个。一个字节有8位,可以代表256种状态,所以一个字节足够纯英文环境下的各种字符。于是很自然的,最早也是应用最广泛的单字节编码ASCII诞生了。

ASCII编码使用一个字节的低7位,最高位为0,编码范围为00000000-0111111,如果用十进制表示,则为0-127。编码分布如下图所示。

writeline

Latin1 编码

ASCII码表只包含英文字母,显然是不够的。首先是西欧国家,主要是拉丁语系。和英语一样,也是字母语言,字符不多,大概几十个。所以使用ASCII最高位的未使用位。编码范围为10000000-1111111,即十进制128-256,包含拉丁字母和一些特殊符号,如欧元符号,这是Latin1编码。可以看出,Latin1编码是ASCII的超集,总共可以表示256个字符。

GB2312、GBK和GB18030编码

在亚洲国家,情况非常复杂。以中文为例,仅满足日常读写需求最常用的最少汉字数量就有3000个左右,这显然不是一个字节所能容纳的。自然,人们认为单字节不够,所以双字节。

最先形成标准的是GB2312。GB2312采用变长编码,即ASCII字符仍用单字节表示,而汉字用两个字节表示。具体的技术规定是:码值小于127的字符含义与ASCII码相同,但当两个码值大于127的字符连在一起时,表示一个汉字,首字节(他称之为高字节)的范围是0xA1到0xF7,末字节(低字节)的范围是0xA1到0xFE。

但是汉字的数量其实比这个数字大很多,而且还有繁体字,所以GB2312很快就不能满足需求了。于是GBK出现了,具体的技术方案从两个方面着手。一个是继续用完GB2312之前没有用完的码位,一个是放宽两个字符的码值都大于127的限制,这样只要第一个字符大于127,就表示是中文。GBK是GB2312的超集,完全兼容GB2312,包含超过20,000个汉字和相关字符,包括繁体汉字。

在GBK,交流基本没有大问题,但还是不能满足文化交流的需要,一些中国的生僻字和少数民族的文字还是不能表达。因此推出了GB18030(全称“信息技术中文编码字符集”)。在GBK的基础上,覆盖范围进一步扩大,包括7万多个汉字、少数民族文字和日韩汉字。由于超出了65535的两字节限制,GB18030采用了变长编码,即一个字符可能是1字节(ASCII字符)、2字节(完全兼容GB2312,基本兼容GBK)、4字节。

Unicode

为了适应我国的需要,许多国家和地区都制定了自己的字符编码。不方便安装相应的解码程序来识别不同编码下的字符。浏览网页时经常出现的乱码,基本都是编码问题造成的。

为了解决这个问题,开发者提出了一种编码,对全世界的各种字符进行编码,并赋予每个字符一个唯一的码位,这就是Unicode。目前Unicode code 空共包含0x10FFFF(1114111)个码点,分为17个平面,每个平面包含0xFFFF或65535个字符。最重要的是基本多语种平面,包含了各种语言中最常用的字符码,码位范围为0x0000-0xFFFF。其他平面称为辅助平面。

自从1991年发布第一个版本以来,每年都有新的字符加入到Unicode中。最新的Unicode标准是14.0.0,共有144,697个字符。需要注意的是,Unicode是一个符号集,一个规范,它为每个字符指定了一个唯一的对应数字,也就是码位。但它并不是一个编码标准,因为它并不涉及如何存储这些码位,即如何存储一个有几个字节的字符,采用的具体技术方案等等。目前,具体的编码标准主要有UTF-8、UTF-16和UTF-32。

UTF-32

UTF-32是一种定长编码,使用4个字节统一表示Unicode字符。这个方案简单明了,码点值是多少,内存中存储多少。好处是空之间每个字符的占用都是一样的,所以在任意位置随机获取字符非常简单,只需要在第一个字符的地址上加一个固定的偏移量,时间复杂度为O(1)。

UTF-32的缺点也很明显,就是空之间的浪费。原来英文字母可以用一个字节表示,现在也需要四个字节。

UTF-16

UTF-16是一种可变长度编码,它使用2个字节或4个字节来存储Unicode码位。

如前所述,Unicode码位的范围是0x000000~0x10FFFF。对于0x0000~0xFFFF的字符,即基本多语言平面,UTF-16用2个字节表示,直接存储码位值。

如果值超过0xFFFF码位,则2个字节不能存储,4个字节用于存储。那么4个字节如何表示一个Unicode码位呢?首先,不能直接存储码位值,因为如果直接存储码位值,前两个字节的值可能与基本的多语种平面中的码位值相同,导致无法区分。其次,四个字节理论上可以存储超过42.9亿个字符,但是Unicode规范只定义了1114111个字符,因为2的20次方大致是1048576,所以几乎只需要20位,也就是两个半字节。

具体方法是将0xFFFF以外的码位值分成两部分,每部分10位。其中,前10位是基本多语种平面未分配的码位范围:0xD800~0xDBFF,可以表示1024种状态。后10位指定为0xDC00~0xDFFF,也可以表示1024个状态,合起来可以表示1024 * 1024 = 1048576个字符,几乎相当于Unicode码位范围,略少,影响不大。

UTF-8

UTF-8也是一种变长码。编码规则是:如果第一个字节的高位为0,即码位在0到127之间,则为单字节编码(ASCII码)。如果第一个字节的高位为1,则为多字节编码。至于2字节和3字节,则是4字节,取决于第一个字节的高位有多少个1。如果属于多字节编码,UTF-8除了第一个字节都是从10开始的。换句话说,UTF-8理论上可以达到8个字节,但由于Unicode目前只有一百多万个码点,最多用4个字节就够了。

单字节编码,形式是 0xxxxxxx,完全兼容ASCII 编码,包含127个字符。双字节编码:形式是 110xxxxx 10xxxxxx,能够容纳 2048 个字符,三字节编码:1110xxxx 10xxxxxx 10xxxxxx,能够容纳65536个字符。四字节编码:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx:能够容纳 2,097,152 个字符,超出了 Unicode 码点范围

UTF-8最大的优点是它的灵活性。如果文本完全是英文,只需要一个字节。汉字大部分是三字节编码,少数是四字节编码。

大端序和小端序

计算机以字节为最小存储单位,也就是说不会在一个字节内拆分。但是如果有两个或者更多的字节(或者单元),那么在存储的时候谁把它们放在前面就有区别了。比如& # 34;马& # 34;一个字的Unicode码值是0x9A6C。当它以两个字节存储时,有两种不同的考虑,即第一个字节9A是放在存储器的前面(在低地址)还是后面(在存储器的高地址)。Big endian是指第一个字节放在低位地址,最后一个字节放在高位地址;否则就是小端。

字节顺序BOM是字节顺序标志。BOM是Unicode标准中的特殊字符FEFF。它没有被定义为任何字符,但建议在Unicode标准中放在文件或数据流的开头,以标识字节存储的顺序。我们都知道它的代码值是FEFF。如果存储为FE FF,说明这个方法是big endian (be),如果存储为FF FE,说明是小尾(le)。

C# 中处理文本编码

在C#中,系统。Text.Encoding提供了对文本编码的基本支持,您可以通过GetEncoding方法获得任何编码实例。

//在。NET Core,必须调用RegisterProvider: encoding。register provider(codepagesencodingprovider。实例)闲暇时;//获取所有的编码foreach(编码中的编码信息info。getencodings ()) {console。writeline(info . name)}//获取GB18030编码var中文编码=编码。get encoding(& # 34;GB18030 & # 34);var utf8Encoding =编码。UTF8C#还为ASCII、Latin1、UTF-8、UTF-16和UTF-32提供了特殊的子类。

Encoding.ASCIIEncoding.Latin1Encoding.UTF8Encoding.Unicode ,UTF-16编码,小端序Encoding.BigEndianUnicod,UTF-16编码,大端序Encoding.UTF32,UTF-32编码,小端序

读取文件时,可以指定编码。如果您不指定它,它将默认为UTF-8。

System.IO.File.WriteAllText ("data.txt", "床前明月光", Encoding.Unicode);

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。

发表回复

登录后才能评论