unicode与gbk双向编码转换(分离底层,便于移植)
程序员文章站
2022-03-31 19:52:28
...
unicode与gbk双向编码转换表在短信解析,FATFS长文件名等都有用到,我一般是将编码表放置于外部falsh,与字库放到一起,本次将编码表的底层进行了分离,并且对编码表进行检测,具体实现如下:
底层存储器接口分离后,可以将编码表存放于内存,内部flash,外部flash,外部TF卡等等地方,代码与平台无关。
unicode_gbk.c
/*************************************************************************************************************
* 文件名 : unicode_gbk.c
* 功能 : 汉字编码转换
* 作者 : [email protected]
* 创建时间 : 2013-04-03
* 最后修改时间 : 2018-03-25
* 详细 : 2018-03-25:增加回调函数支持,用于从存储器读取编码表
*************************************************************************************************************/
#include "system.h"
#include "unicode_gbk.h"
//回调接口-底层数据寄存器接口
static bool (*ReadGbkToUnicodeCode_CallBack)(u8 pData[2], u32 OffsetByteAddr);
static bool (*ReadUnicodeToGbkCode_CallBack)(u8 pData[2], u32 OffsetByteAddr);
/*************************************************************************************************************************
* 函数 : bool GBK_UNICODE_Init(bool (*ReadGbkToUnicodeCode)(u8 pData[2], u32 OffsetByteAddr), bool (*ReadUnicodeToGbkCode)(u8 pData[2], u32 OffsetByteAddr))
* 功能 : 初始化GBK,UNICODE编码表
* 参数 : ReadGbkToUnicodeCode:读取GBK转UNICODE编码表回调函数,OffsetByteAddr:字节偏移地址
ReadUnicodeToGbkCode:读取UNICODE转GBK编码表回调函数,OffsetByteAddr:字节偏移地址
* 返回 : TRUE:初始化成功;FALSE:初始化失败
* 依赖 : 底层读写函数
* 作者 : [email protected]
* 时间 : 2013-04-18
* 最后修改时间 : 2018-13-25
* 说明 : 2018-13-25:增加底层接口回调,必须在底层接口初始化完成后才能进进行调用
*************************************************************************************************************************/
bool GBK_UNICODE_Init(bool (*ReadGbkToUnicodeCode)(u8 pData[2], u32 OffsetByteAddr), bool (*ReadUnicodeToGbkCode)(u8 pData[2], u32 OffsetByteAddr))
{
const u16 GBK_Code = /*'国';//*/0xB9FA; //测试的中文汉字
ReadGbkToUnicodeCode_CallBack = ReadGbkToUnicodeCode; //读取GBK转UNICODE编码表回调函数
ReadUnicodeToGbkCode_CallBack = ReadUnicodeToGbkCode; //读取UNICODE转GBK编码表回调函数
if(ReadGbkToUnicodeCode == NULL || ReadUnicodeToGbkCode == NULL)
{
DEBUG("编码转换表回调函数有误!\r\n");
return FALSE;
}
else
{
if(OneGBKtoUNICODE(GBK_Code) != 0x56FD)
{
DEBUG("GBK to UNICODE编码表检查错误!\r\n");
return FALSE;
}
else if(OneUNICODEtoGBK(0x56FD) != GBK_Code)
{
DEBUG("UNICODE to GBK编码表检查错误!\r\n");
return FALSE;
}
else
return TRUE;
}
}
/*************************************************************************************************************************
* 函数 : u16 OneGBKtoUNICODE(u16 GBKCode)
* 功能 : 将GBK编码转换为unicode编码
* 参数 : GBK
* 返回 : unicode
* 依赖 : 底层读写函数
* 作者 : [email protected]
* 时间 : 20120602
* 最后修改时间 : 20120602
* 说明 : 需要flash中的码表支持
GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/
u16 OneGBKtoUNICODE(u16 GBKCode)
{
u16 unicode;
u8 buff[2];
u16 *p;
u8 ch,cl;
ch = GBKCode >> 8;
cl = GBKCode & 0x00ff;
ch -= 0x81;
cl -= 0x40;
unicode = (ch*0xbf+cl)*2;
ReadGbkToUnicodeCode_CallBack(buff, unicode); //读取GBK转UNICODE编码表
p = (u16 *)buff;
return *p;
}
/*************************************************************************************************************************
* 函数 : u16 OneUNICODEtoGBK(u16 unicode)
* 功能 : 将unicode编码转换为GBK编码
* 参数 : unicode
* 返回 : GBK
* 依赖 : 底层读写函数
* 作者 : [email protected]
* 时间 : 20120602
* 最后修改时间 : 20120602
* 说明 : 需要flash中的码表支持
GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/
u16 OneUNICODEtoGBK(u16 unicode)
{
u32 offset;
u8 temp[2];
u16 res;
if(unicode<=0X9FA5)offset=unicode-0X4E00;
else if(unicode>0X9FA5)//是标点符号
{
if(unicode<0XFF01||unicode>0XFF61) return 0; //没有对应编码
offset=unicode-0XFF01+0X9FA6-0X4E00;
}
ReadUnicodeToGbkCode_CallBack(temp, offset*2); //读取UNICODE转GBK编码表
res=temp[0];
res<<=8;
res+=temp[1];
return res ; //返回找到的编码
}
/*************************************************************************************************************************
* 函数 : void GBKToUnicode(u16 *pGBK, u16 *pUnicode, u32 cnt)
* 功能 : 将多个GBK编码转换为UNICODE
* 参数 : pGBK:GBK编码缓冲区
* pUnicode:UNCODE编码缓冲区
* cnt:转换编码个数
* 返回 : 无
* 依赖 : OneGBKtoUNICODE
* 作者 : [email protected]
* 时间 : 20130403
* 最后修改时间 : 20130403
* 说明 : GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/
void GBKToUnicode(u16 *pGBK, u16 *pUnicode, u32 cnt)
{
while(cnt --)
{
*pUnicode = OneGBKtoUNICODE(*pGBK ++);
pUnicode ++;
}
}
/*************************************************************************************************************************
* 函数 : void UnicodeToGBK(u16 *pUnicode, u16 *pGBK, u32 cnt)
* 功能 : 将多个UNICODE编码转换为GBK
* 参数 : pUnicode:UNCODE编码缓冲区
* pGBK:GBK编码缓冲区
* cnt:转换编码个数
* 返回 : 无
* 依赖 : OneUNICODEtoGBK
* 作者 : [email protected]
* 时间 : 20130403
* 最后修改时间 : 20130403
* 说明 : GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/
void UnicodeToGBK(u16 *pUnicode, u16 *pGBK, u32 cnt)
{
while(cnt --)
{
*pGBK = OneUNICODEtoGBK(*pUnicode ++);
pGBK ++;
}
}
unicode_gbk.h
/*************************************************************************************************************
* 文件名 : unicode_gbk.h
* 功能 : 汉字编码转换
* 作者 : [email protected]
* 创建时间 : 2013-04-03
* 最后修改时间 : 2013-04-03
* 详细 : 2018-03-25:增加回调函数支持,用于从存储器读取编码表
*************************************************************************************************************/
#ifndef UNICODE_GBK_H_
#define UNICODE_GBK_H_
#include "system.h"
bool GBK_UNICODE_Init(bool (*ReadGbkToUnicodeCode)(u8 pData[2], u32 OffsetByteAddr), bool (*ReadUnicodeToGbkCode)(u8 pData[2], u32 OffsetByteAddr));//初始化GBK,UNICODE编码表
u16 OneGBKtoUNICODE(u16 GBKCode); //单个GBK转UNICODE
u16 OneUNICODEtoGBK(u16 unicode); //单个UNICODE转GBK
void GBKToUnicode(u16 *pGBK, u16 *pUnicode, u32 cnt); //将多个GBK编码转换为UNICODE
void UnicodeToGBK(u16 *pUnicode, u16 *pGBK, u32 cnt); //将多个UNICODE编码转换为GBK
#endif /*UNICODE_GBK_H_*/
//初始化
//初始化双向字库编码转换接口-必须在存储器初始化后进行初始化,并且会验证编码表是否正确(存在)
if(GBK_UNICODE_Init(ReadGbkToUnicodeCode, ReadUnicodeToGbkCode) == FALSE)
{
uart_printf("编码表初始化失败\r\n");
}
//接口
///////////////////////////////////////////////////////////////////////////////////////////////////
//GBK与UNICODE双向编码表基址定义(在外部flash 中)
#define CODE_UtoG_BASE (0xBB000) //unicode转GBK码表-在外部falsh中的字节地址
#define CODE_GtoU_BASE (0xC5500) //GBK转unicode码表-在外部falsh中的字节地址
/***********************************************双向字库编码转换表接口************************************************/
//GbkToUnicode编码转换表底层接口,需要先初始化W25XXX芯片
__inline bool ReadGbkToUnicodeCode(u8 pData[2], u32 OffsetByteAddr)
{
W25XXX_Read(&g_SysGlobal.W25X16_Handle, pData, CODE_GtoU_BASE+OffsetByteAddr, 2); //地址加上基址
return TRUE;
}
//UnicodeToGbk编码转换表底层接口,需要先初始化W25XXX芯片
__inline bool ReadUnicodeToGbkCode(u8 pData[2], u32 OffsetByteAddr)
{
W25XXX_Read(&g_SysGlobal.W25X16_Handle, pData, CODE_UtoG_BASE+OffsetByteAddr, 2); //地址加上基址
return TRUE;
}
比如在FATFS中使用,如下:
#include "unicode_gbk.h" //编码转换
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 c;
if (src < 0x80) { /* ASCII */
c = src;
}
else
{
if (dir)
{ /* OEMCP to unicode */
c = OneGBKtoUNICODE(src);
}
else
{ /* Unicode to OEMCP */
c = OneUNICODEtoGBK(src);
}
}
return c;
}
这2个接口,用于从存储器中编码表指定偏移读取数据,W25XXX驱动见:https://blog.csdn.net/cp1300/article/details/79055864
编码表下载地址:https://download.csdn.net/download/cp1300/10361436
上一篇: c++中gbk和utf-8互转