Unicode编码标准以及UTF

编码标准

  • ASCII

    • 美国信息交换标准代码

    • American Standard Code for Information Interchange

    • 显示现代英语和其他西欧语言

    • 128个字符

  • GB2312-80

    • 1980 年制定的中国汉字编码国家标准。共收录 7445 个字符,其中汉字 6763 个。GB2312 兼容标准 ASCII码,采用扩展 ASCII 码的编码空间进行编码,一个汉字占用两个字节,每个字节的最高位为 1。

  • GBK

    • 《汉字内码扩展规范》(GBK) 于1995年制定,兼容GB2312、GB13000-1、BIG5 编码中的所有汉字,使用双字节编码,编码空间为 0x8140~0xFEFE,共有 23940 个码位,其中 GBK1 区和 GBK2 区也是 GB2312 的编码范围。收录了 21003 个汉字。GBK向下与 GB 2312 编码兼容,向上支持 ISO 10646.1国际标准,是前者向后者过渡过程中的一个承上启下的产物。ISO 10646 是国际标准化组织ISO 公布的一个编码标准,即 Universal Multilpe-Octet Coded Character Set(简称UCS),大陆译为《通用多八位编码字符集》,台湾译为《广用多八位元编码字元集》,它与 Unicode 组织的Unicode编码完全兼容。ISO 10646.1 是该标准的第一部分《体系结构与基本多文种平面》。我国 1993 年以 GB 13000.1 国家标准的形式予以认可(即 GB 13000.1 等同于 ISO 10646.1)

  • GB18030

    • 国家标准GB18030-2000《信息交换用汉字编码字符集基本集的补充》是我国继GB2312-1980和GB13000-1993之后最重要的汉字编码标准,是我国计算机系统必须遵循的基础性标准之一。GB18030-2000编码标准是由信息产业部和国家质量技术监督局在2000年 3月17日联合发布的,并且将作为一项国家标准在2001年的1月正式强制执行。GB18030-2005《信息技术中文编码字符集》是我国制订的以汉字为主并包含多种我国少数民族文字(如藏、蒙古、傣、彝、朝鲜、维吾尔文等)的超大型中文编码字符集强制性标准,其中收入汉字70000余个

  • latin1

    • Latin1是ISO-8859-1的别名,有些环境下写作Latin-1。ISO-8859-1编码是单字节编码,向下兼容ASCII,其编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCII一致,0x80-0x9F之间是控制字符,0xA0-0xFF之间是文字符号。

    • ISO-8859-1收录的字符除ASCII收录的字符外,还包括西欧语言、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号。欧元符号出现的比较晚,没有被收录在ISO-8859-1当中。

      因为ISO-8859-1编码范围使用了单字节内的所有空间,在支持ISO-8859-1的系统中传输和存储其他任何编码的字节流都不会被抛弃。换言之,把其他任何编码的字节流当作ISO-8859-1编码看待都没有问题。这是个很重要的特性,MySQL数据库默认编码是Latin1就是利用了这个特性。ASCII编码是一个7位的容器,ISO-8859-1编码是一个8位的容器。

  • Unicode

    • 简述

      • Unicode中文名叫统一码,包含字符集和编码方案。右面的编码标准属于各个机构的方言,方言的弊端就是仅能表达某个特定区域的字符(如:ASCII不能描述汉字,GBK不能描述法文等),而unicode是全球统一语言。如果把各种文字编码形容为各地的方言,那么Unicode就是世界各国合作开发的一种语言。也是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。

      • 基本上,计算机只是处理数字。它们指定一个数字,来储存字母或其他字符。在创造Unicode之前,有数百种指定这些数字的编码系统。没有一个编码可以包含足够的字符:例如,单单欧州共同体就需要好几种不同的编码来包括所有的语言。即使是单一种语言,例如英语,也没有哪一个编码可以适用于所有的字母,标点符号,和常用的技术符号。这些编码系统也会互相冲突。也就是说,两种编码可能使用相同的数字代表两个不同的字符,或使用不同的数字代表相同的字符。任何一台特定的计算机(特别是服务器)都需要支持许多不同的编码,但是,不论什么时候数据通过不同的编码或平台之间,那些数据总会有损坏的危险。

    • 字符集

      • Universal Multiple-Octet Coded Character Set,中文名:通用多八位编码字符集,简称为UCS。这里的UCS = Unicode,只是有的地方叫法不同,但就是一个东西。UCS和Unicode只是分配整数给字符的编码表。

      • UCS-2

        • 2个字节编码

      • UCS-4

    • 编码方式

      • Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位。码位就是可以分配给字符的数字。UTF-8、UTF-16、UTF-32都是将数字转换到程序数据的编码方案。

        现在存在好几种将一串字符表示为一串字节的方法. 最显而易见的两种方法是将Unicode文本存储为2个或4个字节序列的串。这两种方法的正式名称分别为UCS-2和UCS-4,除非另外指定,否则大多数的字节都是这样的(Bigendian convention)。

    • UCS

      • Unicode是基于通用字符集(Universal Character Set)的标准来发展

      • 它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。

    • 与UTF的关系

      • unicode与UTF的关系:Unicode是一套编码标准,UCS是字符集制定了字符与数字之间的对应,UTF标准是在Unicode系统下对UCS的编码实现方式,(比如:某个字符占几个字节,编码顺序,如何存储等)

    • 实现方式

      • UTF

        • UCS Transformation Format:UCS字符集转换格式,或者叫做

          Unicode Transformation Format:Unicode转换格式。

          UTF-8、UTF-16和UTF-32都能存储所有字符,它们的区别在于空间的使用率上。UTF-8在存储ASCII字符集时只需要用一个字节,UTF-32则需要使用固定的四个字节,UTF-16综合表现处于两者之间。

        • 字节序

          • Byte Order Mark

            • 作用

              • 确定字符的值存储的顺序,有两种方式

              • 举例:汉文“字”的16进制编码为:0x5B 57

                • 小尾序

                  • 0x57 5B

                • 大尾序

                  • 0x5B 57

              • UTF-8 with BOM的作用是特殊的,它不是用来确定字节序,而是用来确实编码方式的。 文件的开头三个字节是EF BB BF即表示:我是UTF-8编码的文件而不是UTF-16或者UTF-32。

          • 即在传输字节流前,先传输被作为BOM的字符"零宽无中断空格"。这个字符的编码是FEFF,而反过来的FFFE(UTF-16)和FFFE0000(UTF-32)在Unicode中都是未定义的码位,不应出现在实际传输中。

        • UTF-8

          • 动态长度(1-4个字节),最大程度利用空间,存储扩展字符需要计算

          • 兼容ASCII

          • 与字节序无关,它的字节顺序在所有系统中都是一样的,因此它实际上并不需要BOM。

          • UTF-8 with BOM

            • 文件的前三个字节为: EF BB BF

              • C++读取的话需要一些处理

              • java读取不需要手动进行处理

            • 用来区分UTF-16或UTF-32文本

          • UTF-8 without BOM

            • 相对于UTF-8 with BOM就是文件头没有EF BB BF

        • UTF-16

          • 非固定长度(2或者4个字节),空间利用率和需要的计算综合下来处于UTF-8与UTF-32之间(UTF-32不需要计算,它并非动态,只是空间占用多)。

            UTF-16使用2个字节对全球常用的字符编码USC-2,同时还会使用4个字节对不常用的字符进行编码。

          • 实现依赖字节序

          • UTF-16LE

            • 小端顺序(也称作:小尾序)

              • 值的低位存储在前面

            • BOM:FF FE

          • UTF-16BE

            • 大端顺序(也称作:大尾序)

              • 值的高位在前面

            • BOM:FE FF

          • 字符集:UCS-2,和部分UCS-4字符集

          • UTF-16大尾序和小尾序文件在C++都不需要特殊处理

        • UTF-32

          • UTF-32是 简单的编码方法,该方法用一个32位的内存空间(也就是4字节)存储一个字符编码,由于Unicode字符集的 大个数为0x10FFFF(ISO 10646),因此4字节的空间完全能够容纳任何一个字符编码。UTF-32编码方法的优点显而易见,它非常简单,计算字符串长度和查找字符都很方便;缺点也很明显,太占用内存空间。

          • 固定长度:4字节

          • 字符集:UCS-4

          • UTF-32LE

            • FF FE 00 00

          • UTF-32BE

            • 00 00 FE FF

        • 在主流编程语言中的使用

          • java

            • java使用UTF-16表示内部文本,并支持用于字符串串行化的非标准的修正UTF-8编码(可占6个字节)。

          • C++

            • wchar_t

              头文件<cuchar>

              提供多字节字符到宽字符的互转

              size_t mbrtoc16(char16_t* pc16, const char* s, size_t n, mbstate_t* ps);

              size_t c16rtomb(char* s, char16_t c16, mbstate_t* ps);

              size_t mbrtoc32(char32_t* pc32, const char* s, size_t n, mbstate_t* ps);

              size_t c32rtomb(char* s, char32_t c32, mbstate_t* ps);

              • unicode编码的字符一般以wchar_t类型存储,但wchar_t不等于Unicode,根据系统标准不同占16位或32位

              • 最主要的问题是在Windows上是16位,而在Linux和macOS上wchar_t却是32位的(4字节)。这导致了一个严重的后果,我们写出的代码无法在不同平台上保持相同行

                为。而char16_t和char32_t的出现解决了这个问题,它们明确规定了其所占内存空间的大小,让代码在任何平台上都能够有一致的表现。

                • std::codecvt_utf8 是封装 UTF-8 编码字符串和 UCS2 或 UTF-32 字符串(取决于 Elem 类型)间转换的 std::codecvt 平面。此 codecvt 能用于读写文本和二进制的 UTF-8 文件。

                  readTextFileStream.imbue(locale(locale::classic(), new codecvt_utf8<wchar_t>));

              • 中文名:宽字符

            • char16_t对应UTF-16

              • 字面量编码:u"文字"

            • char32_t对应UTF-32

              • 字面量编码:U"文字"

            • C++17 新增了char8_t 来表示 UTF-8

              • 字面量编码:u8"文字"

C++检查一个文件是否UTF-8 with BOM

	{
		char *pcstr = new char[4];
		ifstream inputFileStream("./someword2.txt", ios_base::binary);
		long realReadSize = 3;
		inputFileStream.getline(pcstr, 4);
		if (realReadSize == 3)
		{
			cout << hex << pcstr[0] << pcstr[1] << pcstr[2] << endl;
			if ((unsigned char)pcstr[0] == 0xEF && (unsigned char)pcstr[1] == 0xBB && (unsigned char)pcstr[2] == 0xBF)
			{
				cout << "this text file is UTF-8 with BOM" << endl;
			}
		}
		// 检查一个文本文件是否UTF-8 with BOM
	}

猜你喜欢

转载自blog.csdn.net/wangxudongx/article/details/125126524