这几天在做一个读取UTF8文件的功能,其中包括中英文。
在UTF8中,不同的字符集下的字符宽度是不等的,比如 英文和符号都用1个Byte来表示,中文就需要用2-3个byte来表示,因此在从一个UTF8字符串中获取一个字符的时候就需要先判断该字符应该占几个字节。
根据UTF8 编码, 首字节的编码包含了整个字符占用几个字节的 信息,参见下表(右边一栏为UTF8编码)
xxx 的位置由字符编码数的二进制表示的位填入. 越靠右的 x 具
知道了这些知识,基本就可以自己写段代码出来来截取所需要的字符个数了。
这个功能在 D语言的标准库 phobos 中是有的, 参见 std.utf 包的 stride函数。
在std.utf包中,这个功能使用了一个 256个自己的查找表,直接查找返回字节长度。
不过,上面的代码也好还是 std.utf 包中的函数也好,都 没有对后续字节进行验证,并 不能保证指定宽度的字节是一个正确的utf8字符。这一点还需要使用者在使用时自行判断。
另:在 std.utf 包中常用的 utf 字符处理的功能都有了,只需要简单组合就可以实现自己的应用了,很是方便。
在UTF8中,不同的字符集下的字符宽度是不等的,比如 英文和符号都用1个Byte来表示,中文就需要用2-3个byte来表示,因此在从一个UTF8字符串中获取一个字符的时候就需要先判断该字符应该占几个字节。
根据UTF8 编码, 首字节的编码包含了整个字符占用几个字节的 信息,参见下表(右边一栏为UTF8编码)
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: | 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx |
U-04000000 - U-7FFFFFFF: | 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx |
知道了这些知识,基本就可以自己写段代码出来来截取所需要的字符个数了。
D 代码
- int u8CharWidth(char[] u8string, uint start)
- {
-
- if((u8string[start] & 0xFE) == 0xFC)
- {
- return 6;
- }
- if((u8string[start] & 0xFC) == 0xF8)
- {
- return 5;
- }
- if((u8string[start] & 0xF8) == 0xF0)
- {
- return 4;
- }
- if((u8string[start] & 0xF0) == 0xE0)
- {
- return 3;
- }
- if((u8string[start] & 0xE0) == 0xC0)
- {
- return 2;
- }
- if((u8string[start] & 0x80) == 0x00)
- {
- return 1;
- }
- return -1;
- }
这个功能在 D语言的标准库 phobos 中是有的, 参见 std.utf 包的 stride函数。
在std.utf包中,这个功能使用了一个 256个自己的查找表,直接查找返回字节长度。
不过,上面的代码也好还是 std.utf 包中的函数也好,都 没有对后续字节进行验证,并 不能保证指定宽度的字节是一个正确的utf8字符。这一点还需要使用者在使用时自行判断。
另:在 std.utf 包中常用的 utf 字符处理的功能都有了,只需要简单组合就可以实现自己的应用了,很是方便。