Go语言中多字节字符的处理方法详解
1概述
Go语言的字符串是使用UTF-8编码的。UTF-8是Unicode的实现方式之一。本文内容包括:UTF-8和Unicode的关系,Go语言提供的unicode包和unicode/utf8包的使用。
下面话不多说了,来一起看看详细的介绍吧
2UTF-8和Unicode的关系
Unicode一种字符集,是国际标谁化组织(ISO)设计的一个包括了地球上所有文化、所有字母和符号的编码。他们叫它UniversalMultiple-OctetCodedCharacterSet,简称UCS,也就是Unicode。Unicode为每一个字符分配一个唯一的码点(CodePoint),就是一个唯一的值。例如康的码点就是24247,十六进制为5eb7。
Unicode字符集仅仅定义了字符与码点的对应关系,但是并没有定义该如何编码(存储)这个码值,这就导致了很多问题。例如由于字符的码值不同,导致所需要的存储空间是不一致的,计算机不能确定接下来的字符是占用几个字节。还有就是如果采用固定的长度假设都是4个字节来存储码点值,那么会导致空间的额外浪费,因为ascii码字符其实仅仅需要一个字节的空间。
UTF-8就是解决如何为Unicode编码而设计的一种编码规则。可以说UTF-8是Unicode的实现方式之一。其特点是一种变长编码,使用1到4个字节表示一个字符,根据不同的符号而变化长度。UTF-8的编码规则有二:
- 对于单字节的符号,字节的第一位设为0,后面7位为这个符号的Unicode码。因此对于ASCII码字符,UTF-8编码和ASCII码是相同的。
- 对于n字节的符号(n>1,2到4),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的Unicode码。
以下是编码规则:
Unicode|UTF-8 --------------------------------------------------------- 00000000-0000007F|0xxxxxxx 00000080-000007FF|110xxxxx10xxxxxx 00000800-0000FFFF|1110xxxx10xxxxxx10xxxxxx 00010000-0010FFFF|11110xxx10xxxxxx10xxxxxx10xxxxxx ---------------------------------------------------------
Go语言中,对于Unicode和UTF-8使用了unicode和unicode/utf8包来实现,下面是阅读API的总结和说明。
3Unicode包
Go语言中,提供了Unicode包,处理与Unicode相关的操作,整理如下:
Is(rangeTab*RangeTable,rrune)bool
检测runer是否在rangeTable指定的字符范围内。
rangeTable一个Unicode码值集合,通常使用unicode包中定义的集合。
判断字符是否出现在汉字集合中:
unicode.Is(unicode.Scripts["Han"],'k') //返回false unicode.Is(unicode.Scripts["Han"],'康') //返回true
In(rrune,ranges…*RangeTable)bool
检测runer是否在多个rangeTable指定的字符范围内。
rangeTable一个Unicode码值集合,通常使用unicode包中定义的集合。
unicode.In('康',unicode.Scripts["Han"],unicode.Scripts["Latin"]) //返回true unicode.In('k',unicode.Scripts["Han"],unicode.Scripts["Latin"]) //返回true
IsOneOf(ranges[]*RangeTable,rrune)bool
检测runer是否在rangeTableranges指定的字符范围内。与In功能类似,推荐使用In。
IsSpace(rrune)bool
检测字符runer是否是空白字符。在Latin-1字符空间中,空白字符为:
'\t','\n','\v','\f','\r','',U+0085(NEL),U+00A0(NBSP)
其它的空白字符请参见策略Z和属性Pattern_White_Space。
IsDigit(rrune)bool
检测字符runer是否是十进制数字字符。
unicode.IsDigit('9') //返回true unicode.IsDigit('k') //返回false
IsNumber(rrune)bool
检测字符runer是否是Unicode数字字符。
IsLetter(rrune)bool
检测一个字符runer是否是字母
unicode.IsLetter('9') //返回false unicode.IsLetter('k') //返回true
IsGraphic(rrune)bool
一个字符runer是否是unicode图形字符。图形字符包括字母、标记、数字、符号、标点、空白。
unicode.IsGraphic('9') //返回true unicode.IsGraphic(',') //返回true
IsControl(rrune)bool
检测一个字符runer是否是unicode控制字符。
IsMark(rrune)bool
检测一个字符runer是否是标记字符。
IsPrint(rrune)bool
检测一个字符runer是否是的可打印字符,基本与图形字符一致,除ASCII空白字符U+0020。
IsPunct(rrune)bool
检测一个字符runer是否是unicode标点字符。
unicode.IsPunct('9') //返回false unicode.IsPunct(',') //返回true
IsSymbol(rrune)bool
检测一个字符runer是否是unicode符号字符。
IsLower(rrune)bool
检测一个字符runer是否是小写字母。
unicode.IsLower('h') //返回true unicode.IsLower('H') //返回false
IsUpper(rrune)bool
检测一个字符runer是否是大写字母。
unicode.IsUpper('h') //返回false unicode.IsUpper('H') //返回true
IsTitle(rrune)bool
检测一个字符runer是否是Title字符。大部分字符的Title格式就是其大写格式,少数字符的Title格式是特殊字符,例如ᾏᾟᾯ。
unicode.IsTitle('ᾯ') //返回true unicode.IsTitle('h') //返回false unicode.IsTitle('H') //返回true
To(_caseint,rrune)rune
将字符runer转换为指定的格式,格式_case支持:unicode.UpperCase、unicode.LowerCase、unicode.TitleCase
unicode.To(unicode.UpperCase,'h') //返回H
ToLower(rrune)rune
将字符runer转换为小写。
unicode.ToLower('H') //返回h
func(SpecialCase)ToLower
将字符runer转换为小写。优先使用映射表SpecialCase。
映射表SpecialCase是特定语言环境下大小写的映射表。主要应用于一些欧洲字符,例如土耳其TurkishCase。
unicode.TurkishCase.ToLower('İ') //返回i
ToUpper(rrune)rune
将字符runer转换为大写。
unicode.ToUpper('h') //返回H
func(SpecialCase)ToUpper
将字符runer转换为大写。优先使用映射表SpecialCase。
映射表SpecialCase是特定语言环境下大小写的映射表。主要应用于一些欧洲字符,例如土耳其TurkishCase。
unicode.TurkishCase.ToUpper('i') //返回İ
ToTitle(rrune)rune
将字符runer转换为Title字符。
unicode.ToTitle('h') //返回H
func(SpecialCase)ToTitle
将字符runer转换为Title字符。优先使用映射表SpecialCase。
映射表SpecialCase是特定语言环境下大小写的映射表。主要应用于一些欧洲字符,例如土耳其TurkishCase。
unicode.TurkishCase.ToTitle('i') //返回İ
SimpleFold(rrune)rune
在unicode标准字符映射中查找与runer互相对应的unicode码值。向码值大的方向循环查找。互相对应指的是同一个字符可能出现的多种写法。
unicode.SimpleFold('H') //返回h unicode.SimpleFold('Φ')) //返回φ
4unicode/utf8包
DecodeLastRune(p[]byte)(rrune,sizeint)
解码[]bytep中最后一个UTF-8编码序列,返回该码值和长度。
utf8.DecodeLastRune([]byte("小韩说课")) //返回358383 //35838就是课的unicode码值
DecodeLastRuneInString(sstring)(rrune,sizeint)
解码strings中最后一个UTF-8编码序列,返回该码值和长度。
utf8.DecodeLastRuneInString("小韩说课") //返回358383 //35838就是课的unicode码值
DecodeRune(p[]byte)(rrune,sizeint)
解码[]bytep中第一个UTF-8编码序列,返回该码值和长度。
utf8.DecodeRune([]byte("小韩说课")) //返回235673 //23567就是小的unicode码值
DecodeRuneInString(sstring)(rrune,sizeint)
解码strings中第一个UTF-8编码序列,返回该码值和长度。
utf8.DecodeRuneInString("小韩说课") //返回235673 //23567就是小的unicode码值
EncodeRune(p[]byte,rrune)int
将runer的UTF-8编码序列写入[]bytep,并返回写入的字节数。p满足足够的长度。
buf:=make([]byte,3) n:=utf8.EncodeRune(buf,'康') fmt.Println(buf,n) //输出[229186183]3
FullRune(p[]byte)bool
检测[]bytep是否包含一个完整UTF-8编码。
buf:=[]byte{229,186,183}//康 utf8.FullRune(buf) //返回true utf8.FullRune(buf[:2]) //返回false
FullRuneInString(sstring)bool
检测strings是否包含一个完整UTF-8编码。
buf:="康"//康 utf8.FullRuneInString(buf) //返回true utf8.FullRuneInString(buf[:2]) //返回false
RuneCount(p[]byte)int
返回[]bytep中的UTF-8编码的码值的个数。
buf:=[]byte("小韩说课") len(buf) //返回12 utf8.RuneCount(buf) //返回4
RuneCountInString(sstring)(nint)
返回strings中的UTF-8编码的码值的个数。
buf:="小韩说课" len(buf) //返回12 utf8.RuneCountInString(buf) //返回4
RuneLen(rrune)int
返回runer编码后的字节数。
utf8.RuneLen('康') //返回3 utf8.RuneLen('H') //返回1
RuneStart(bbyte)bool
检测字节byteb是否可以作为某个rune编码的第一个字节。
buf:="小韩说课" utf8.RuneStart(buf[0]) //返回true utf8.RuneStart(buf[1]) //返回false utf8.RuneStart(buf[3]) //返回true
Valid(p[]byte)bool
检测切片[]bytep是否包含完整且合法的UTF-8编码序列。
valid:=[]byte("小韩说课") invalid:=[]byte{0xff,0xfe,0xfd} utf8.Valid(valid) //返回true utf8.Valid(invalid) //返回false
ValidRune(rrune)bool
检测字符runer是否包含完整且合法的UTF-8编码序列。
valid:='a' invalid:=rune(0xfffffff) fmt.Println(utf8.ValidRune(valid)) //返回true fmt.Println(utf8.ValidRune(invalid)) //返回false
ValidString(sstring)bool
检测字符串strings是否包含完整且合法的UTF-8编码序列。
valid:="小韩说课" invalid:=string([]byte{0xff,0xfe,0xfd}) fmt.Println(utf8.ValidString(valid)) //返回true fmt.Println(utf8.ValidString(invalid)) //返回false
完!
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。