欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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