汉字转拼音占内存更少转换速度更快的程序

汉字转拼音占内存更少转换速度更快的程序

作者:admin |  时间:2014-10-12 |  浏览:635 |  0 条评论

程序地址:https://github.com/jishipu/Chinese2Pinyin

借鉴使用Redis字符操作库SDS,简化程序编写,提高安全性和可移植性。

本汉字转拼音程序仅支持输入字符串是utf-8编码的情况,其它编码,程序会不做处理

原文输出。

将常见20902个汉字的拼音按照unicode编码的大小排序写到文件PinyinData.txt中,

因为汉字的拼音最长占6个字节,如chuang等,故每个拼音在文件中占6个字节,所以

有的拼音后面会含有空格。

汉字最小unicode码是19968, 将一个汉字的unicode码减去19968,乘以6,

得到其在PinyinData.txt中的偏移量,然后通过fseek定位到该位置,读取6个字节,

去掉后面可能含有的空格,就得到该汉字的拼音。

    //tmp是汉字的unicode码,start=19968,MAX_PINYIN_LEN=6
    int offset = (tmp - start) * MAX_PINYIN_LEN;
    //fp是PinyinData.txt的描述符
    fseek(fp, offset, SEEK_SET);
    fread(buf, MAX_PINYIN_LEN, 1, fp);

如何得到一个汉字的unicode码呢?

unicode编码中所有的字符都占两个字节,这种编码方法使得保存纯英文文本时会多占

用一倍的空间。utf-8是unicode编码的一种最常见的网络传输标准。

utf-8编码每次检查一个字节:

值在00000000~01111111(0~127)范围,确定是单字节字符, 指针要向后移动一个位置;

值在11000000~11011111(192~223)范围,确定是2字节字符,指针要向后移动两个位置;

值在11100000~11101111(224~239)范围,确定是3字节字符,指针要向后移动三个位置;

值在11110000~11110111(240~247)范围,确定是4字节字符,指针要向后移动四个位置;

值在11111000~11111011(248~251)范围,确定是5字节字符,指针要向后移动五个位置;

值在11111100~11111101(252~253)范围,确定是6字节字符,指针要向后移动六个位置;

100000000~10111111(128~191)标识的字节,不可能是字符的首字节,只可能是后续字节。

汉字在utf-8中占用三个字节。所以如果发现字节值在224~239之间,可以向后多读取两个字节,

这三个字节标识一个汉字。

我们先看unicode编码到utf-8的转换规则:

    0000 – 007F
    0xxxxxxx
    0080 – 07FF
    110xxxxx 10xxxxxx
    0800 – FFFF
    1110xxxx 10xxxxxx 10xxxxxx

例如“汉”字的unicode编码是0x6C49, 0x6C49在0800~FFFF之间,所用要用3字节模板:

1110xxxx 10xxxxxx 10xxxxxx, 将6C49写成二进制是:0110 1100 0100 1001, 按照三字节模板的

分段方法:0110 110001 001001, 依次替换模板中的x, 得到:1110-0110 10-110001 10-001001,

即E6 B1 89, 这就是“汉”字的utf-8编码。

反之,我们得到“汉”的utf-8编码11100110 10110001 10001001,按照下面的规则就可以得到其unicode编码:

/*
 * words指向当前读到的字节,并且字节范围在224~239之间。
 * ((int)(*words & 0x0F)) << 12) => 0110 0000 0000 0000
 * (((int)(*(words+1) & 0x3F)) << 6) => 1100 0100 0000
 * (*(words+2) & 0x3F) => 1001
 * 0110 0000 0000 0000 | 1100 0100 0000 | 0010 0100 => 0110 1100 0100 1001 => 6C49
 */
(((int)(*words & 0x0F)) << 12) | (((int)(*(words+1) & 0x3F)) << 6) | (*(words+2) & 0x3F);

得到“汉”字的unicode码是0x6C49, 转为10进制是27721, (27721 - 19968) * 6 = 46518, 使用fseek函数

将fp定位到46518,读取6个字节,去掉后面空格后,得到"han", 获取拼音成功。

综上,本程序采用文件定位的方法转换拼音,占用内存少,并且速度快,应该是一个很不错的方案。

发表评论

电子邮件地址不会被公开。

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>