上篇文章《GBK转unicode码查询表》中有一个美中不足的地方,就是占用的内存空间稍大了一点,约128KB,当然,对于PC这种平台无所谓,但对于一些场合来说,能省内存就省内存,何况那个表省内存又是件很easy的事情。

首先说明,平时使用GBK汉字编码字符集就够用了。GB18030向下兼容GBK,所以在文章、代码直接称GBK了。对于这些标准细则,有兴趣的可以深究一下。

再说说修改的地方,其实,经过观察生成的查询表,就发现,前面128个字符就是ASCII码,完全不用去查询表(实际代码中也没有去查),ASCII码后面有N个unicde码是0x00,只占地方,完全无用。所以,只要找到unicode非零的最低的GBK码即可。经多方查证(包括研究上篇文章给出的文本文件以及百度搜索),发现有用的最小的GBK码是0x8140。这个是什么字符,我不太懂,可参考地址:http://ff.163.com/newflyff/gbk-list/。比这个值小的都没有在GBK编码中找到。因此,我们的表中只需要存储这个值以后的GBK对应的unicode编码即可。这样一来,就可以节省一半的空间了(实际占用62.9KB)。在查询函数中,将字符的GBK码减去0x8140即可得到查询表中正确的unicode码。

上述方法不复杂,也不难想到。与我之前存储ASCII字符方法一样,即不去存储95个ASCII码,而只存储从0x20开始的ASCII码,在查询时,将传入的字符减去0x20即可。

下面给出修改后的程序(修改地方不多,一个是存储查询表时,从0x8140开始,另一个是在查询过程中将GBK减去0x8140)。

生效查询表程序代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define ARRAY "gbkuni30"
#define MAX_LEN 65535   // 2字节最大数
static unsigned short big_buffer[MAX_LEN] = {0};

// 源文件
#define SRC "gbkuni30.txt"

// 生产的头文件
#define DST "gbkuni30_gen.h"

int make_charmap_gb18030()
{
    char buffer[16] = {0};
    char* p = NULL;
    FILE* fp_c = NULL;
    FILE* fp = NULL;
    int len = 0;
    int x1 = 0;
    int x2 = 0;
    int i = 0;
    int max_num = 0;
    int cnt = 0;

fp = fopen(SRC, "r");
    if (fp == NULL)
    {
        printf("open file error!!\n");
        return -1;
    }

fseek(fp, 0, SEEK_END);
    len = ftell(fp);
    fseek(fp,0,SEEK_SET);

printf("file len: %d\n", len);

fp_c = fopen(DST, "w+");
    if (fp_c == NULL)
    {
        printf("open file error!!\n");
        return -1;
    }

fprintf(fp_c, "/**********************************************************************************/\n");
    fprintf(fp_c, "/*             GBK(GB18030) to UNICODE table, powered by Late Lee                 */\n");
    fprintf(fp_c, "/*                        http://www.latelee.org                                  */\n");
    fprintf(fp_c, "/*                         %s %s                                   */\n", __DATE__, __TIME__);
    fprintf(fp_c, "/* The source file comes from:                                                    */\n");
    fprintf(fp_c, "/* http://icu-project.org/repos/icu/data/trunk/charset/source/gb18030/gbkuni30.txt*/\n");
    
    fprintf(fp_c, "/**********************************************************************************/\n");

fprintf(fp_c, "#ifndef __GBK2UNICODE__H\n");
    fprintf(fp_c, "#define __GBK2UNICODE__H\n\n");

fprintf(fp_c, "");
    fprintf(fp_c, "static unsigned short %s[] = \n{\n", ARRAY);

// 先读取到缓冲区,解析出两个数
    while (fgets(buffer, 32, fp) != NULL)
    {
        sscanf(buffer, "%x:%x\n", &x1, &x2);
        
        //printf("%s", buffer);
        //printf("%04x %x\n", x1, x2);
        //fprintf(fp_c, "0x%04x, 0x%x,\n", x1, x2);
        big_buffer[x2] = x1;
        if (x2 > max_num)
            max_num = x2;

}

printf("max num: %d %x\n", max_num, max_num);
    // 注:为节省存储空间,从0x8140开始存储,查询时需要减去此数
    for (i = 0x8140; i < max_num + 1; i++)
    {
        //printf("0x%04x\n", big_buffer[i]);
        fprintf(fp_c, "0x%04x, ", big_buffer[i]);
        cnt++;
        if (cnt % 10 == 0)
        {
            fprintf(fp_c, "    // line num %d \n", cnt / 10 - 1);
        }
    }
    fprintf(fp_c, "\n");
    fprintf(fp_c, "};\n\n");
    fprintf(fp_c, "#endif //__GBK2UNICODE__H\n");
    fprintf(stdout, "Job done!\n");

fclose(fp);
    fclose(fp_c);

return 0;

}

转换查询函数如下:

/**
 * gbk字符串转unicode字符串
 *
 * @param unicode  unicode字符串
 * @param gb       gbk字符串
 * @param len      gbk字符串长度
 *
 * @return 返回转换后的unicode字符串长度(1个字符占2字节)
 *
 * @note 
 *         1. 所有字符的unicode编码为2字节??
 *         2. 必须使用unsigned char进行移位计算,否则结果不正确
 */
int gbk_to_unicode(unsigned short int* unicode, const char* gb, int len)
{
    int i,j;
    i = 0;
    unsigned char* gb_temp = (unsigned char *)gb;   // 必须转换成无符号

for(j = 0; i < len; j++)
    {
        if (gb_temp[i] <= 0x80)
        {
            unicode[j] = gb_temp[i];
            i++;
        }
        else
        {
            unsigned short int temp;
            //printf("%x %x\n", gb_temp[i], gb_temp[i+1]);
            temp = (gb_temp[i] << 8) + gb_temp[i+1];
            temp -= 0x8140; // 查询表从0x8140开始存储,故减去此数
            unicode[j] = gbkuni30[temp];
            i += 2;
            //printf("debug: gbk: 0x%x unicode: 0x%x\n", temp+0x8140, unicode[j]);
        }
    }

return j;
}

对于代码优化,我还有比较注意的,举个例子,有个接口需要修改RGB颜色值,要是我设计的话,肯定将RGB三个颜色值合成一个int型参数。但我看的代码中,是将三个值分开传递的,这样,无端多了几个参数。经询问,得到的解释是:用户可读性强。对此,我不作评论。在公司层面上讲,我绝对服从组织上的决定。

记于文后:

对于汉字及编码,很早我就开始搞了,只是没时间研究那么深。写了现在这篇文章后,估计不会在这方面再作研究了。再研究下去也没多大意思。

迟,记于2013年8月24日晚上

GBK转unicode码查询表的改进相关推荐

  1. 使用python实现GBK转unicode码查询表

    接触python有一段时间了,但没有专门学习基础知识,写代码时总是到网上找资料.不过,相信经过练习可以慢慢积累.本文拿以前写的小程序练手.参见文章<GBK转unicode码查询表的改进>. ...

  2. GBK转unicode码查询表

    大约大半年前完成一个矢量字库类,使用freetype库从矢量字库中读取字符轮廓,然后转成只有0.1的缓冲区,可以使用许多场合.涉及了freetype的操作,同时还有字符编码方面的知识.前不久,有同事反 ...

  3. 汉字编码(【Unicode】 【UTF-8】 【Unicode与UTF-8之间的转换】 【汉字 Unicode 编码范围】【中文标点Unicode码】【GBK编码】【批量获取汉字UNICODE码】)

    参考博客: Unicode与UTF-8互转(C语言实现):http://blog.csdn.net/tge7618291/article/details/7599902 汉字 Unicode 编码范围 ...

  4. [编码]ASCII、GBK、Unicode(万国码) 和 UTF-8

    American ASCII编码 (American Standard Code for Information Interchange,美国信息互换标准代码)  China    gbk编码     ...

  5. ASCII、GB2312、GBK、Unicode、UTF-8介绍和转换

    1.ASCII码 上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定.这被称为 ASCII 码,一直沿用至今.ASCII 码一共规定了128个字符的编码,比如空格S ...

  6. Visual Studio——多字节编码与Unicode码

    多字节字符与宽字节字符 1) char与wchar_t 我们知道C++基本数据类型中表示字符的有两种:char.wchar_t.  char叫多字节字符,一个char占一个字节,之所以叫多字节字符是因 ...

  7. es6=unicode码详解

    字符的Unicode表示法 JavaScript允许采用\uxxxx形式表示一个字符,其中xxxx表示字符的Unicode码点. "\u0061" // "a" ...

  8. 字符集ASCII、GBK、UNICODE、UTF在储存字符时的区别

    ASCII编码(American Standard Code for Information Interchange,美国信息互换标准代码),使用127个8进制字节表示英文和半角字符. GBK (Gu ...

  9. java打印unicode_java程序实现Unicode码和中文互相转换

    有了前一篇文章的了解,大概了解了unicode编码格式了 ANSI:汉字区的内码范围高字节从B0-F7,低字节从A1-FE Unicode:汉字的Unicode编码范围为\u4E00-\u9FA5 \ ...

最新文章

  1. ASP.NET中实现大结果集分页研讨 转
  2. 120万公里「真」无人商用里程如何炼成?出租车物流车车车无人,香港乌鲁木齐城城自动...
  3. Word保存自己格式模板的方法
  4. C# 委托 (一)—— 委托、 泛型委托与Lambda表达式
  5. Android 拉起小程序页面进行传值
  6. c语言小项目-使用mysql数据库的图书管理系统
  7. linux c 子线程sleep,linux c之sleep的多种实现
  8. mysql 查新格式化_mysql 日期格式化查询
  9. Android--音乐播放器
  10. 跟随报文,开启一段奇妙之旅
  11. Android ListView中 每一项都有不同的布局
  12. linux里面的命令
  13. win7 64位装sql2000
  14. php旧物交易开源代码_PHP学习笔记:php二手交易市场系统
  15. Learun.framework快速开发框架-功能特点与手机app
  16. 三维点云语义地图 TSDF
  17. 世界前五大IT咨询公司
  18. libcurl入门之相关接口函数curl_easy_getinfo
  19. 【百度分享】BZFS—一种透明压缩文件系统
  20. 【浙江大学计算机学院】ccnt实验室之,CCNT实验室

热门文章

  1. 在页脚里显示本页统计数据_外卖营业统计里的数据您能看懂吗?
  2. 努比亚Z40 Pro定档2月25日:业界唯一定制35mm主摄+首发索尼IMX787
  3. 被曝大裁员,涉及30%员工!公司内斗、高管之间拉帮结派 喜茶回应了...
  4. 宁德时代:拟70亿投建储能电池项目
  5. 因2800万美元太贵 演员汤姆·汉克斯拒绝贝佐斯上太空邀请
  6. 苹果支付招聘业务开发经理 需有加密货币支付工作经验
  7. 跟谁学宣布独立调查结论:没有造假 盘后股价涨超8%
  8. 罗永浩回应被限制高消费:已跟债权方达成和解
  9. Model Y已成特斯拉今年交付量第二高车型 前8个月交付2.9万辆
  10. 9月30日或成年内最难打车日 滴滴1亿补贴鼓励司机师傅多接单