学习笔记-关于字符集ANSI

来源:互联网 发布:查看环境变量 linux 编辑:程序博客网 时间:2024/06/11 05:42

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
原创粉丝点击