美文网首页iOSiOS Developer
OC 字符串编码-中英文字符串混合长度

OC 字符串编码-中英文字符串混合长度

作者: 熊猫人和熊猫君 | 来源:发表于2017-06-19 21:26 被阅读210次

    1.各种编码格式 原理以及发展历史

    1.1 ASCII码

    早起计算机发展初期,肯定是以字母为标准的,没考虑世界上其他语言 如中文,日文韩文等,故此起初设计的字符集合也就比较简单,也就是如今的ASCII码。
    ASCII码一共规定了128个字符的编码,比如大写的字母A是65(二进制01000001)。这128个符号(包括32个不能打印出来的控制符号),只占用了一个字节的后面7位,最前面的1位统一规定为0。

    1.2. 非ASCII码

    英语用128个符号编码就够了,但是用来表示其他语言,128个符号是不够的。比如,在法语中,字母上方有注音符号,它就无法用ASCII码表示。需要扩展编码集合有些就使用ASCII码保留码有些,有些就使用两个字节来表示如国标GB2312就是两个字节表示一个汉字。但是各个地区国家各自为政发展出来了很多不同的非ASCII码体系,如台湾与大陆编码都不一样,这导致沟通成本很大,故此迫切需要一个标准化的符号集合,Unicode孕育而生。

    1.3.Unicode

    Unicode只是一个符号集合,规定了二进制代码,但是并没规定具体存储方式。
    对应具体的汉字有可能其Unicode需要二个字节来保存其转换出来的二进制数,也有可能需要3个字节,4个字节才能够保存,大部分汉字是需要4个字节来表示。
    比如,汉字“严”的unicode是十六进制数4E25,转换成二进制数足足有15位(100111000100101),也就是说这个符号的表示至少需要2个字节。表示其他更大的符号,可能需要3个字节或者4个字节,甚至更多。

    这里就有两个严重的问题,第一个问题是,如何才能区别unicode和ascii?计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?第二个问题是,我们已经知道,英文字母只用一个字节表示就够了,如果unicode统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。

    它们造成的结果是:1)出现了unicode的多种存储方式,也就是说有许多种不同的二进制格式,可以用来表示unicode。2)unicode在很长一段时间内无法推广,直到互联网的出现。

    1.4.UTF-8
    UTF-8是Unicode的实现方式之一,其他实现方式还包括UTF-16和UTF-32,不过在互联网上基本不用。
    互联网的普及,人们的快去要沟通越来越频繁,强烈要求出现一种统一的编码方式,UTF-8就此诞生。

    UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。

    UTF-8的编码规则很简单,只有二条:
    1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
    2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

    UTF-8 每字至少 1 byte,至多 4 bytes。1 byte 字符与 US-ASCII 相符。U+0800-07ff 是 2 bytes,0800-ffff 是 3 bytes,之后的是 4 bytes

    下表总结了编码规则,字母x表示可用编码的位。
    Unicode符号范围 | UTF-8编码方式

    image.png

    下面,还是以汉字“严”为例,演示如何实现UTF-8编码。
    已知“严”的unicode是4E25(100111000100101),根据上表,可以发现 4E25处在第三行的范围内(0000 0800-0000 FFFF),因此“严”的UTF-8编码需要三个字节,即格式是“1110xxxx 10xxxxxx 10xxxxxx”。然后,从“严”的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,“严”的UTF-8编码是 “11100100 10111000 10100101”,转换成十六进制就是E4B8A5。

    2.实际使用场景

    2.1 需求:求中英文混合长度

    从上可做字符串的长度取决于我们的字符编码方式,如国标GB2312那就一个汉字两个字节,字母一个字节,如UTF-8,一个汉字是动态的长度2个字节到4个字节之间,千万别再说一个汉字在UTF-8这种unicode实现方式上是3个字节了,日韩字符集合是四个字节,当然常用的中文大部分落在3个字节范围内。所以说标准的约定很重要,客户端内部的约定,客户端与服务器端的约定。只有形成了标准才能交流实现。客户端与服务器端标准不同话,各自算出的长度都不一样,如某些场景需要截断字符串,那么就容易出问题了,客户端明明告诉服务器端截取多少个,可因为标准的不同多截了或者少截了,导致一些bug。

      NSString * text = @"1234刘a";
      NSInteger length = [text length]; //length值为6,length仅仅返回字符个数而不是存储空间大小
      NSInteger length_utf8 = [text lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; //length_utf8值为8
    
      NSString * text1 = @"刘";
      NSInteger length_utf8 = [text lengthOfBytesUsingEncoding:NSUTF8StringEncoding];//length_utf8值为3
    

    可见在NSUTF8StringEncoding存储形式下的unicode,中文“刘”字,占存储空间为3个字节,字符与数字均为一个字节

    相关文章

      网友评论

        本文标题:OC 字符串编码-中英文字符串混合长度

        本文链接:https://www.haomeiwen.com/subject/cshjqxtx.html