当前位置: 首页 > GNU/Linux程序 > 正文

GBK转unicode码查询表

大约大半年前完成一个矢量字库类,使用freetype库从矢量字库中读取字符轮廓,然后转成只有0、1的缓冲区,可以使用许多场合。涉及了freetype的操作,同时还有字符编码方面的知识。前不久,有同事反映说我提供的东西不能生成“绿”字。经测试,的确如此。查找代码发现原来编码转换表不全面,没有“绿”字的unicode码。那个对应表是在网上找的,自己也没做全面测试——我不会无聊到所有的汉字都测试一遍。
后来仔细一想,觉得有必要自己生成一个自己看得懂的查询表,并且比较全面的。于是找啊找,不小心找到了一个专门介绍编码的网站,找到了一个号称是GB18030和unicode对应的文本文件。具体地址是:http://icu-project.org/repos/icu/data/trunk/charset/source/gb18030/gbkuni30.txt。这个网站还有其它许多有用的资料,虽然是英文的,但认真看看,十分有用。至于如何查找,有志之士应该十分清楚,就不在此献丑了(写到这里,突然想到,在许多工作时间中,许多东西都有手把手教——甚至一些简单的东西,看来这种做法要改改了)。
为了在程序中使用那个表,于是自己写了生成查询表的小程序。程序很简单,就是直接用上述地址的文件生成一个一维数组。网上有类似的表,有的数组是二维的,查找不方便。下面的程序生成的是数组是按照GBK编码排序的,就是说,直接用GBK的编码查找数组即得到unicode码。比如,汉字“绿”的GBK编码是0xc2cc,则数组的第0xc2cc偏移的值就是“绿”的unicode编码:0x7eff。
完整代码如下:

#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 fileerror!!\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 fileerror!!\n"); return -1; } fprintf(fp_c, "/**********************************************************************************/\n"); fprintf(fp_c, "/* GBK(GB18030) to UNICODE table, powered by LateLee */\n"); fprintf(fp_c, "/* http://www.latelee.org */\n"); fprintf(fp_c, "/* %s%s */\n", __DATE__, __TIME__); fprintf(fp_c, "/* The source file comesfrom: */\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); for (i = 0; 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码函数如下:

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; temp = (gb_temp[i] << 8) + gb_temp[i+1]; unicode[j] = gbkuni30[temp]; i += 2; } } return j; }

注意上面的函数的寻址方式,这里会涉及到大小端的问题,寻址方式一定要和生成的查询表对应。这里转换得到的temp的值就是汉字的GBK码,直接查找数组即得到unicode码。
测试函数如下:

void main() { make_charmap_gb18030(); printf("total len:%d(%.1fKB)\n", sizeof(gbkuni30), sizeof(gbkuni30) / 1024.0); const char* p="啊"; int len = (int)strlen(p); unsigned short* unicode = new unsigned short[len]; int unicode_len = 0; unicode_len = gbk_to_unicode(unicode, p, len); for (int i = 0; i < unicode_len; i++) { printf("gbk: %02x %02x,unicode: %x\n", p[i], p[i+1], unicode[i]); } }

参考资料:
Unicode、GB2312、GBK和GB18030中的汉字:http://www.fmddlmyy.cn/text24.html
GB18030编码研究以及GBK、GB18030与Unicode的映射:http://www.fmddlmyy.cn/text30.html
浅谈文字编码和Unicode(上):http://www.fmddlmyy.cn/text16.html
浅谈文字编码和Unicode(下)::http://www.fmddlmyy.cn/text17.html

迟,写于2013年8月18日睡前

本文固定链接: http://www.latelee.org/programming-under-linux/gbk-to-unicode-table.html

如无特别说明,迟思堂工作室文章均为原创,转载请注明: GBK转unicode码查询表 | 迟思堂工作室

目前暂无评论

发表评论

*

快捷键:Ctrl+Enter