制作UTF8转GB2312转换库
来源:互联网 发布:张予曦淘宝店的模特 编辑:程序博客网 时间:2024/06/08 08:54
UTF8转GB2312
由于工作中要适配佳博58系列的热敏打印机,而目前开发驱动打印的产品采用的字符编码格式是UTF8,而查看手册时发现该打印机采用的是GB2312格式编码的,若UTF8编码格式直接打印输出中文或全角符号,则是一堆乱码,于是需要转换格式,网上可用的开源库有libiconv。移植过后发现该库对于我的产品来说略显大。而我只需要UTF8转GB2312,于是准备自己动手。
链接:https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.15.tar.gz 移植过程网上自行百度。
知识点:
- UTF8是UNICODE的子集,因此它们之间是有着对应关系
- UNICODE与GB2312并无对应关系,因此需要建立对应关系表
- UTF8格式属于变长编码格式长度1-6字节,GB2312属于定长编码格式1-2字节(其中1字节区属于ASCII编码区域)
UTF8与UNICODE之间的关系如下:
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: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
首字节有几个1就代表此UTF8格式编码是由几个字节编码的。(若是首字节是0则代表为ASCII码)
转换过程核心点在于此。
因此判断有几个1则使用以下代码:
int GetUtf8ChNum(unsigned char first){ unsigned char tmp = 0x80; int count = 0; while(tmp & first) { count++; tmp = (tmp >> 1); } return count;}
查表函数如下(经典二分法,速度非常块)
#define GB2312CodeSize 21791//GB2312编码此大小固定值unsigned short SearchCode(unsigned short unicodeVal){ int first = 0; int end = GB2312CodeSize - 1; int mid = 0; while(first <= end) { mid = (first + end) / 2; if(code_table[mid].unicode == unicodeVal) { return code_table[mid].gb; } else if(code_table[mid].unicode > unicodeVal) { end = mid - 1; } else { first = mid + 1; } } return 0;}
UTF8最大有6个字节编码,GB2312最大2个字节编码,而GB2312在UTF8所处的编码区间是3个字节的区间因此就根据返回值处理3个字节和1个字节的UTF8的编码即可。
void Utf8ToGb2312(const unsigned char* utf8, unsigned char *gb2312, int len){ int i = 0; int j = 0; int Count = 0; u16 unicodeVal = 0; u16 gb2312Val = 0; //循环查表找出对应GB2312码 while(i < len) { switch(GetUtf8ChNum(utf8[i])) { case 0: gb2312[j] = utf8[i]; Count = 1; break; case 2: gb2312[j] = utf8[i]; gb2312[j + 1] = utf8[i + 1]; Count = 2; break; case 3://UTF8->Unicode gb2312[j + 1] = ((utf8[i] & 0x0F) << 4) | ((utf8[i + 1] >> 2) & 0x0F); gb2312[j] = ((utf8[i + 1] & 0x03) << 6) + (utf8[i + 2] & 0x3F); memcpy(&unicodeVal, (gb2312 + j), 2);//取Unicode值 gb2312Val = SearchCode(unicodeVal);//根据unicodeVal值查表取得对应的GB2312值 if (gb2312Val != 0)//gb2312有值表示查到表中对应编码,转换大小端以适应我的设备 { gb2312Val = (gb2312Val >> 8) | (gb2312Val << 8); memcpy((gb2312 + j), &gbKey, 2); } Count = 3; break; case 4: Count = 4; break; case 5: Count = 5; break; case 6: Count = 6; break; default: printf("Unknown code, len > 6\n"); break; } i += Count; if (Count == 1) { j++; } else { j += 2; } }}
附录:表的格式,本次是作为头文件包含。
网上的格式是这样:
unicode GB231200A4 A1E800A7 A1EC00A8 A1A700B0 A1E3............此处省略N行............FFE0 A1E9FFE1 A1EAFFE3 A3FEFFE5 A3A4
链接http://blog.csdn.net/longronglin/article/details/1355890
头文件中排序之后是这样:
typedef struct unicode_gb{ unsigned short unicode; unsigned short gb;} UNICODE_GB;UNICODE_GB code_table[] = {{0x00A4,0xA1E8},{0x00A7,0xA1EC},{0x00A8,0xA1A7},......此处省略N行......{0xFFE2,0xA956},{0xFFE3,0xA3FE},{0xFFE4,0xA957},{0xFFE5,0xA3A4}};
源文件大小:
再编译成库,大小感人:
再看看libiconv-1.15.tar.gz编译出来的库大小:
一个1.3M
验证库:
自此打印机可以肆无忌惮的打印中文啦~~由于调试,金额可以随便指定,只是个样子而已啦!
若要源码,以及对照表,则从此处下载,发布在我的资源中
链接:http://download.csdn.net/download/skyblue535/9991713
- 制作UTF8转GB2312转换库
- C# 编码转换 UTF8转GB2312 GB2312转UTF8
- C# 编码转换 UTF8转GB2312 GB2312转UTF8
- C# 编码转换 UTF8转GB2312 GB2312转UTF8
- C# 编码转换 UTF8转GB2312 GB2312转UTF8
- UTF8 - GB2312转换
- UTF8、GB2312相互转换
- url 编码转换(utf8 - gb2312)
- url 编码转换(utf8 - gb2312)
- UTF8 到GB2312 的 转换
- GB2312和utf8编码转换
- js 编码转换 gb2312 & utf8
- C++ UTF8 编码转换 GB2312
- utf8 和 gb2312 的转换
- GB2312与UTF8相互转换
- UTF8和GB2312编码转换
- GB2312与UTF8互相转换
- gb2312和utf8相互转换:
- 三亚旅游攻略----蜜月记
- 3D动画电影
- LitePal简单用法
- IT热门技能
- 深入分析Java的序列化与反序列化
- 制作UTF8转GB2312转换库
- Solr报错-503-Server is shutting down or failed to initialize
- 【LeetCode】Search For A Range 区间搜索[二分法]
- 助力全国双创周,天英汇领衔打造区域创新新势力
- word中页眉页码使用真谛
- canvas绘制七巧板
- 单例与序列化的那些事儿
- 使用Java中的Try-With-Resource
- Ruby魅力之旅