学习笔记-关于字符集ANSI

ANSI,即多字节字符集,它不同于Unicode的地方在与英文字符以1字节存储。标准的ASCII码表没有使用到大于127的值,而ANSI字符集则有[128, 255]的对应字符,有种物尽其用的思想。

至于不同国家的ANSI字符集使用的编码方式均遵循ANSI编码,以2字节存储。之所以不用前面所说的UTF8是因为太浪费,比如中文的字符'我',以ANSI编码需要2字节,而UTF8需要3字节,因此就出现了GB2312这样的ANSI编码,不同的ANSI编码都有一套自己的字符集,因为UTF8是Unicode字符集的一种实现方式,所以可以通过一定规律实现他们之间的互转,但像GB2312和Unicode之间其实是没有什么对应关系的,所以要互转的话只能通过他们之间的字符值映射来实现。

查看GB2312字符集便可以发现字符值还是有一定规律的,因此可以通过前面说的MultiByteToWideChar来找到GB2312字符值所对应的Unicode值,同时生成一个字符值映射表,这样便可通过查找对应字符的Unicode值来将GB2312字符转换成Unicode字符了。

这是一种生成映射表的方式,中间过程,随便写的,把最后那个长度定义提前就行了:

void cgb()
{
unsigned char gb[3];
gb[2] = 0;
wchar_t w;
int num = 0;
char buff[256];
char tmp[50];
char tmp1[4];
gb[0] = 0xa1;
FILE* f = fopen("c:/gb.h", "a+");
sprintf(buff, "const unsigned short Gb2Unicode[GBLEN][2] = {\r\n ");
fwrite(buff, 1, lstrlenA(buff), f);
while(gb[0] < 0xf8)//计算方式需参考GB2312字符编码表
{
gb[1] = 0xa1;
while(gb[1] < 0xff)
{
int ii1 = MultiByteToWideChar(CP_ACP, 0, (char*)gb, 2, &w, 1);
if(ii1)
{
sprintf(tmp1, "");
sprintf(tmp, "%X", (u_short)w);
int ns = 4 - strlen(tmp);
while(ns-- > 0)
{
strcat(tmp1, "0");
}
sprintf(tmp, "%s%X", tmp1, (u_short)w);
num++;
if(num % 5 == 0)
{
sprintf(buff, "{0X%X, 0X%s}, \r\n ", ntohs(*(u_short*)gb), tmp);
}
else
{
sprintf(buff, "{0X%X, 0X%s}, ", ntohs(*(u_short*)gb), tmp);
}
fwrite(buff, 1, lstrlenA(buff), f);
}
gb[1]++;
}
gb[0]++;
}
sprintf(buff, "\r\n};\r\nconst int GBLEN = %d;\r\n", num);
fwrite(buff, 1, lstrlenA(buff), f);
fclose(f);
}

这样得到的字符映射表基于BG2312的编码值是递增的,因此可以使用二分查找提高效率,具体转换过程如下

static unsigned short find(unsigned short src, int l, int r)
{
if(r > l)
{
int n = (r + l + 1) / 2;
if(Gb2Unicode[n][0] == src)
{
return Gb2Unicode[n][1];
}
else if(src > Gb2Unicode[n][0])
{
return find(src, n + 1, r);
}
else
{
return find(src, l, n - 1);
}
}
else if( r == l)
{
if(Gb2Unicode[l][0] == src)
{
return Gb2Unicode[l][1];
}
}
return 0;
}


unsigned short h2ns(unsigned short hs)
{
unsigned char tmp[2];
tmp[0] = ((unsigned char*)&hs)[1];
tmp[1] = ((unsigned char*)&hs)[0];
return *(unsigned short*)tmp;
}


void GBToUnicode(wchar_t* szOut, int nOut, char* szBuff, int nBuff)
{
int i = 0, j = 0, num = 0;
unsigned short ch;
while(j < nOut && i < nBuff)
{
ch = *(szBuff + i);
num = 1;
if(ch > 0xff)
{

//跟UTF8一样,GB2312也是大端存储,这是小端机器
ch = find(h2ns(*(unsigned short*)(szBuff + i)), 0, GBLEN);
if(ch)
memcpy(&szOut[j], &ch, 2);
else
memcpy(&szOut[j], "?", 2);
num = 2;
}
else
memcpy(&szOut[j], &ch, 2);
i += num;
j++;
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值