单片机中UTF-8如何转换得到GBK编码
概述
我们在单片机开发中常会遇到需要将UTF-8转换为GBK编码的需求。
在我们了解各种编码格式的情况下可知, UFT-8不能直接转成GBK,需中转成unicode再转换为gbk。而unicode和gbk之间没有算法可以直接计算,需要查表方式获取。
这个表有前辈已经整理好了,可直接使用。我们可以在相关资料中得到相关文件。
文件介绍
CC932.C -->日本的Japanese Shift-JIS编码
CC936.C -->Simplified Chinese GBK 编码
CC949.C -->朝鲜的Korean EUC-KR编码
CC950.C -->Traditional Chinese Big5编码
代码解读
const WCHAR uni2oem[]__attribute__((at(0x8005000)))= {
/* Unicode - OEM, Unicode - OEM, Unicode - OEM, Unicode - OEM */0x00A4, 0xA1E8, 0x00A7, 0xA1EC, 0x00A8, 0xA1A7, 0x00B0, 0xA1E3,0x00B1, 0xA1C0, 0x00B7, 0xA1A4, 0x00D7, 0xA1C1, 0x00E0, 0xA8A4,0x00E1, 0xA8A2, 0x00E8, 0xA8A8, 0x00E9, 0xA8A6, 0x00EA, 0xA8BA,
在CC936.C中我们发现有这两个数组,这两个数组则是Unicode和GBK之间的对应关系。
WCHAR ff_convert ( /* Converted code, 0 means conversion error */WCHAR chr, /* Character code to be converted */UINT dir /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */
)
{const WCHAR *p;WCHAR c;int i, n, li, hi;if (chr < 0x80) { /* ASCII */c = chr;} else {if (dir) { /* OEMCP to unicode */p = oem2uni;hi = sizeof(oem2uni) / 4 - 1; //除于4是因为4个字节为一组,所以除于4,减1是因为二分法原理} else { /* Unicode to OEMCP */p = uni2oem;hi = sizeof(uni2oem) / 4 - 1;}li = 0;for (n = 16; n; n--) { //循环16次的原因是2^16次方一定能够找到i = li + (hi - li) / 2;if (chr == p[i * 2]) break; // p[i * 2]原因是:0、2、4...才是unicode数据if (chr > p[i * 2])li = i;elsehi = i;}c = n ? p[i * 2 + 1] : 0; //后一个字节则为gbk码数据}return c;
}
ff_convert()函数通过二分查找法,通过二分查找法能够完成,Unicode和gbk编码的相互转换。但是这两个数组会很大,所以在单片机中一般需存在外部存储器,如flash中。
如何在单片机上完成,UTF-8转GBK呢?
- 我们可以借助工具将CC936.C编码的数组转成BIN文件存入flash中。
- 把UTF-8转换成unicode码
- 根据二分法查找,找到对应的gbk码。
UTF-8与unicode的相互转换函数如下:
int enc_get_utf8_size(const unsigned char pInput){unsigned char c = pInput;// 0xxxxxxx 返回0// 10xxxxxx 不存在// 110xxxxx 返回2// 1110xxxx 返回3// 11110xxx 返回4// 111110xx 返回5// 1111110x 返回6if(c< 0x80) return 0;if(c>=0x80 && c<0xC0) return -1;if(c>=0xC0 && c<0xE0) return 2;if(c>=0xE0 && c<0xF0) return 3;if(c>=0xF0 && c<0xF8) return 4;if(c>=0xF8 && c<0xFC) return 5;if(c>=0xFC) return 6;}/* 将一个字符的UTF8编码转换成Unicode(UCS-2和UCS-4)编码. * * 参数: * pInput 指向输入缓冲区, 以UTF-8编码 * Unic 指向输出缓冲区, 其保存的数据即是Unicode编码值, * 类型为unsigned long . * * 返回值: * 成功则返回该字符的UTF8编码所占用的字节数; 失败则返回0. * * 注意: * 1. UTF8没有字节序问题, 但是Unicode有字节序要求; * 字节序分为大端(Big Endian)和小端(Little Endian)两种; * 在Intel处理器中采用小端法表示, 在此采用小端法表示. (低地址存低位) ****************************************************************************/
int enc_utf8_to_unicode_one(const unsigned char* pInput, unsigned long *Unic)
{ // b1 表示UTF-8编码的pInput中的高字节, b2 表示次高字节, ... char b1, b2, b3, b4, b5, b6; int utfbytes; unsigned char *pOutput; *Unic = 0x00; // 把 *Unic 初始化为全零 pOutput = (unsigned char *)Unic;utfbytes= enc_get_utf8_size(*pInput); //先得到UTF-8的长度switch ( utfbytes ) { case 0: *pOutput = *pInput; utfbytes += 1; break; case 2: b1 = *pInput; b2 = *(pInput + 1); if ( (b2 & 0xE0) != 0x80 ) return 0; *pOutput = (b1 << 6) + (b2 & 0x3F); *(pOutput+1) = (b1 >> 2) & 0x07; break; case 3: b1 = *pInput; b2 = *(pInput + 1); b3 = *(pInput + 2); if ( ((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80) ) return 0; *pOutput = (b2 << 6) + (b3 & 0x3F); *(pOutput+1) = (b1 << 4) + ((b2 >> 2) & 0x0F); break; case 4: b1 = *pInput; b2 = *(pInput + 1); b3 = *(pInput + 2); b4 = *(pInput + 3); if ( ((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80) || ((b4 & 0xC0) != 0x80) ) return 0; *pOutput = (b3 << 6) + (b4 & 0x3F); *(pOutput+1) = (b2 << 4) + ((b3 >> 2) & 0x0F); *(pOutput+2) = ((b1 << 2) & 0x1C) + ((b2 >> 4) & 0x03); break; case 5: b1 = *pInput; b2 = *(pInput + 1); b3 = *(pInput + 2); b4 = *(pInput + 3); b5 = *(pInput + 4); if ( ((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80) || ((b4 & 0xC0) != 0x80) || ((b5 & 0xC0) != 0x80) ) return 0; *pOutput = (b4 << 6) + (b5 & 0x3F); *(pOutput+1) = (b3 << 4) + ((b4 >> 2) & 0x0F); *(pOutput+2) = (b2 << 2) + ((b3 >> 4) & 0x03); *(pOutput+3) = (b1 << 6); break; case 6: b1 = *pInput; b2 = *(pInput + 1); b3 = *(pInput + 2); b4 = *(pInput + 3); b5 = *(pInput + 4); b6 = *(pInput + 5); if ( ((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80) || ((b4 & 0xC0) != 0x80) || ((b5 & 0xC0) != 0x80) || ((b6 & 0xC0) != 0x80) ) return 0; *pOutput = (b5 << 6) + (b6 & 0x3F); *(pOutput+1) = (b5 << 4) + ((b6 >> 2) & 0x0F); *(pOutput+2) = (b3 << 2) + ((b4 >> 4) & 0x03); *(pOutput+3) = ((b1 << 6) & 0x40) + (b2 & 0x3F); break; default: return 0; break; } return utfbytes;
} /***************************************************************************** * 将一个字符的Unicode(UCS-2和UCS-4)编码转换成UTF-8编码. * * 参数: * unic 字符的Unicode编码值 * pOutput 指向输出的用于存储UTF8编码值的缓冲区的指针 * outsize pOutput缓冲的大小 * * 返回值: * 返回转换后的字符的UTF8编码所占的字节数, 如果出错则返回 0 . * * 注意: * 1. UTF8没有字节序问题, 但是Unicode有字节序要求; * 字节序分为大端(Big Endian)和小端(Little Endian)两种; * 在Intel处理器中采用小端法表示, 在此采用小端法表示. (低地址存低位) * 2. 请保证 pOutput 缓冲区有最少有 6 字节的空间大小! ****************************************************************************/
int enc_unicode_to_utf8_one(unsigned long unic, unsigned char *pOutput)
{ if ( unic <= 0x0000007F ) { // * U-00000000 - U-0000007F: 0xxxxxxx *pOutput = (unic & 0x7F); return 1; } else if ( unic >= 0x00000080 && unic <= 0x000007FF ) { // * U-00000080 - U-000007FF: 110xxxxx 10xxxxxx *(pOutput+1) = (unic & 0x3F) | 0x80; *pOutput = ((unic >> 6) & 0x1F) | 0xC0; return 2; } else if ( unic >= 0x00000800 && unic <= 0x0000FFFF ) { // * U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx *(pOutput+2) = (unic & 0x3F) | 0x80; *(pOutput+1) = ((unic >> 6) & 0x3F) | 0x80; *pOutput = ((unic >> 12) & 0x0F) | 0xE0; return 3; } else if ( unic >= 0x00010000 && unic <= 0x001FFFFF ) { // * U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx *(pOutput+3) = (unic & 0x3F) | 0x80; *(pOutput+2) = ((unic >> 6) & 0x3F) | 0x80; *(pOutput+1) = ((unic >> 12) & 0x3F) | 0x80; *pOutput = ((unic >> 18) & 0x07) | 0xF0; return 4; } else if ( unic >= 0x00200000 && unic <= 0x03FFFFFF ) { // * U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx *(pOutput+4) = (unic & 0x3F) | 0x80; *(pOutput+3) = ((unic >> 6) & 0x3F) | 0x80; *(pOutput+2) = ((unic >> 12) & 0x3F) | 0x80; *(pOutput+1) = ((unic >> 18) & 0x3F) | 0x80; *pOutput = ((unic >> 24) & 0x03) | 0xF8; return 5; } else if ( unic >= 0x04000000 && unic <= 0x7FFFFFFF ) { // * U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx *(pOutput+5) = (unic & 0x3F) | 0x80; *(pOutput+4) = ((unic >> 6) & 0x3F) | 0x80; *(pOutput+3) = ((unic >> 12) & 0x3F) | 0x80; *(pOutput+2) = ((unic >> 18) & 0x3F) | 0x80; *(pOutput+1) = ((unic >> 24) & 0x3F) | 0x80; *pOutput = ((unic >> 30) & 0x01) | 0xFC; return 6; } return 0;
}
单片机中读取外部flash中的转换表完成转换,函数如下:
WCHAR ff_convert ( /* Converted code, 0 means conversion error */WCHAR src, /* Character code to be converted */UINT dir /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */
)
{WCHAR t[2];WCHAR c;u32 i, li, hi;u16 n; u32 gbk2uni_offset=0; if (src < 0x80)c = src;//ASCII,直接不用转换.else {if(dir) //GBK 2 UNICODE{gbk2uni_offset=ftinfo.ugbksize/2; //得到数据的偏移地址,双向转换的两个数组在一起}else //UNICODE 2 GBK { gbk2uni_offset=0; } /* Unicode to OEMCP */hi=ftinfo.ugbksize/2;//对半开.hi =hi / 4 - 1;li = 0;for (n = 16; n; n--){i = li + (hi - li) / 2; W25QXX_Read((u8*)&t,ftinfo.ugbkaddr+i*4+gbk2uni_offset,4);//读出4个字节 if (src == t[0]) break;if (src > t[0])li = i; else hi = i; }c = n ? t[1] : 0; }return c;
}
单片机中UTF-8如何转换得到GBK编码相关推荐
- mysql gbk编码 字节数,mysql中utf-8编码数据库转换成GBK编码的问题
摘要 腾兴网为您分享:mysql中utf-8编码数据库转换成GBK编码的问题,之了课堂,易信,一折包邮,星球联盟等软件知识,以及七日杀,草莓软件,装修施工站,桔子会,桌面切换,看小说神器,酷派应用商店 ...
- Python:UTF-8编码转换成GBK编码
2019独角兽企业重金招聘Python工程师标准>>> #!/usr/bin/env python # -*- coding:utf-8 -*- #UTF-8转换成GBK编码 #te ...
- python声明编码为gbk_python入门:UTF-8转换成GBK编码
1 #!/usr/bin/env python 2 #-*- coding:utf-8 -*- 3 #UTF-8转换成GBK编码 4 #temp(临时雇员,译音:泰坡) 5 #decode(编码,译音 ...
- C#编写Rtf文档,中文与字母区分,C#将汉字转换成GBK编码
最近两天在调试仰邦的LED双色屏.他们用的控制卡只能支持三种自定义传参方式,一.文本传值,二.Rtf文档传值,三.bmp图片传值.第一种第三种在仓库中传值无法做到.其主要原因是传的数据比较的多.对于R ...
- AVR单片机中ATmega8的AD转换探究
AD采集最好要满足的条件:采样频率不小于被采集信号最高频率的两倍,则采样输出信号就可以无失真的重新啊还原输入信号,通常的实际应用中,采样频率为采集最高频率的5-10倍. AD芯片的数据输出方式有串行和 ...
- linux 字符集转换命令,Linux下GBK编码到UTF-8文件编码转换方法
Linux命令行下查看看文件的编码 enca 文件名 Linux文件名编码批量转换 convmv -f 源编码 -t 新编码 [选项] 文件名 常用参数: -r 递归处理子文件夹 --notest 真 ...
- C#怎么将GBK编码转换成UTF-8编码?
C#怎么将GBK编码转换成UTF-8编码? private void ChangeEncode(Encoding fromCoding,Encoding toCoding,string fileNam ...
- python中的进制转换以及浮点数二进制转换
为什么要注意这三点: 1.首先是项目中用到的进制转换,常用的int ord hex 以及编写的转换函数,作为记录 2.其次是python 3相对于旧版主要的区别就在这里,主要是bytes 和 stri ...
- android utf-8 转 gbk编码,【字符编码系列】GBK,UTF-8,UTF-16之间的转换
写在前面的话 本文属于 字符编码系列文章之一,更多请前往 字符编码系列. 大纲 不同编码转换的理论基础 UTF-16转UTF-8 UTF-16转GBK UTF-16和UTF-8之间的转换 UTF-16 ...
最新文章
- 区块链还可以这么玩?“点亮莫高窟”背后的腾讯云区块链
- block为什么用copy以及如何解决循环引用
- plsql连接不上64位oracle,plsql develope连接64位Oracle 11g出错解决方案(图)
- 算法学习:后缀自动机
- 2.2.1 静态成员
- 学用 ASP.Net 之 System.Char 结构
- 大连a货翡翠,东莞a货翡翠
- linux 卸载kde,Ubuntu KDE终端系统安装与卸载
- 回溯算法团灭子集、排列、组合问题
- java 配置文件 路径问题_java 配置文件的路径问题
- java 子进程id,Java程序如何获得自己的进程ID?
- python之_init_函数的简介
- IDL | 实验三、IDL编程演练
- 关于ubuntu下无线网卡经常连不上网络的问题
- 父与子的编程之旅 python 3_python3-父与子的编程之旅第十五章
- python员工信息管理_用Python实现职工信息管理系统
- java数组排序的方法_Java数组排序方法详解
- IADS Revision Note 1: Asymptotic Notations
- 如何编译 cm12 (for 一加手机)
- html设置文字超过字数_CSS限制字数,超出部份显示点点点...