C++截取定长utf8字符及字符集与字符编码总结
之前有个需求要求从一段utf8编码的文字中截取前n个字符,由于文字中包含既有中文又有数字字母等,这些字符所占的字节数都不相同,所以直接截取前M个字符可能会导致乱码问题。在完成截取之前,需要先了解utf8编码字符的存储规则。后面简单介绍一下常见的字符集及字符编码
utf8编码规则
在理解utf8编码规则之前先说一下utf16和utf32的编码规则,utf32规定所有的unicode字符集上的所有字符都是用32bit来存储,即可存储的字符数可达2^32个,接近40亿,这明显可以容纳已有的所有字符。utf16编码使用2个字节存储,超过此范围的使用其他特殊技巧处理。使用utf16和utf32有一个问题,就是会受到计算机存储大端规则和小端规则的影响。所以utf16又有utf16_LE和utf16_BE之分。为了解决这个问题,需要在文本文件的开头定义一个BOM(Byte order Mark),这是一个非打印标志,用此标志来标志当前文本存储是大端存储还是小端存储。
utf8是一种针对unicode的可变长度字符编码,也是一种前缀码,它可以表示unicode标准中的任何字符。且与ascii码兼容,这使得我们处理ascii字符的时候不许做特殊修改。
utf8使用1~6个字符为每个字符编码,但实际使用中只使用了4个。
utf8编码规则:
(1)对于单字节字符,字节的第一位为0,后面7位为这个字符的unicode码,因此对于ascii码,unicode与ascii保持一致。
(2)对于n字节符号(n>1),第一个字节的前n位都为1,第n+1位为0,其他字节的前两位都为10,其余位为实际的unicode位。
规则:
unicode范围 | 二进制表示范围 |
---|---|
U-00000000 - U-0000007F | 0xxxxxxx |
U-00000080 - U-000007FF | 110xxxxx 10xxxxxx |
U-00000800 - U-0000FFFF | 1110xxxx 10xxxxxx 10xxxxxx |
U-00010000 - U-001FFFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
U-00200000 - U-03FFFFFF | 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx |
U-04000000 - U-7FFFFFFF | 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx |
利用上述utf8编码规则实现C++截取定长字符串。
字符集与字符编码
字符集是一个系统所支持的字符的集合,常见的字符集包括ascii字符集,GB2312字符集,GBK字符集以及unicode字符集。其中ascii字符集包括所有的英文字母数字以及控制字符等等。
字符编码是用来定义计算机中某个字符的存储和传输规则。
区别:字符集仅仅是一个字符集合,与计算机的存储和传输没有关系,而字符编码规定了计算机中字符的编码规则。
常见的字符集及字符编码
- ascii字符集及字符编码:使用一个字符编码,包括所有的字母数字,换行以及控制字符等。
- GB*字符集及编码:是一种多字节编码标准,GB表示国标,包括GB2312,GBK等编码,2312是标准号,GB2312涵盖了绝大多数的中文,但是一些生僻字不包含在其中,GBK是对GB2312的扩展.
- BIG*:常见的为BIG5字符集及编码,BIG5中收录了大部分的中文繁体,常用语香港台湾等地区。
- unicode字符集及编码:unicode又称为统一码,几乎涵盖了所有国家和地区的所有字符,并还在不断的扩充新字符。unicode是一个字符集,而不是编码规则,我们常见的utf8,utf16以及utf32是unicode常见的字符编码.