学习笔记-关于字符集Unicode

字符集是将一个数值对应到一个字符的映射表,有Unicode和ANSI之分,Unicode为通用字符集,而对于ANSI(多字节)来说,不同的国家有其不同的字符集,如中文的GB2312字符集等。

字符编码是字符集的存储实现,如Unicode编码的2字节存储以及ANSI的多字节存储。

概念容易混乱,ANSI和Unicode是字符集没错,但同时也是一种字符编码。

Unicode编码中所有的字符都是以2字节存储,而英文字母的存储实际只需要1个字节,因此相对于以英文为母语的国家来说,这样的存储方式是一种极大的浪费,UTF8编码也就应运而生。它是Unicode字符集的另一种编码实现形式,具体细节如下:

1字节 0xxxxxxx 
2字节 110xxxxx 10xxxxxx 
3字节 1110xxxx 10xxxxxx 10xxxxxx 
4字节 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 
5字节 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 
6字节 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

其中的x对应的是Unicode字符集中的值,可以看出:

以1个字节表示一个字符时可以表示的Unicode值为[0, 0X7F]

以2个字节表示一个字符时可以表示的Unicode值为(0X7F, 0X7FF]

以3个字节表示一个字符时可以表示的Unicode值为(0X7FF, 0XFFFF]

以4个字节表示一个字符时可以表示的Unicode值为(0XFFFF, 0X10FFFF]

Unicode字符集目前只存在于这个范围之内,而实际中UTF8还可以实现更多的字符。

对于一字节实现的字符,其实际值与ASCII码值一致,而对于多字节实现的字符,最高位字节从高位开始连续的1的位数表示了这个字符是以多少个字节实现的,而除最高字节外,其他字节的高位均以10开头,最高位在连续的1之后也需补一个0,剩下的x所表示的便是此字符对应的Unicode值。

UTF8编码的多字节存储在小端机器上是大端存储,大端机器没有接触过。

C语言实现的Unicode与UTF8编码的转换,参照MultiByteToWideChar和WideCharToMultiByte的功能实现

int UnicodeToUTF8(const wchar_t* szSrc, int nSrc, char* szDest, int nDest)
{
int i = 0;
unsigned int num;
for(int j = 0; j < nSrc; j++)
{
num = (UINT)szSrc[j];
if(num <= 0x007f)//1 byte
{
szDest[i++] = num;
}
else if(num > 0x007f && num <= 0x000007ff)//2 bytes
{
szDest[i++] = 0xc0 + (0x1f & (num >> 6));//bigendian
if(i >= nDest) break;
szDest[i++] = 0x80 + (0x3f & num);
}
else if(num > 0x000007ff && num <= 0x0000ffff)//3 bytes
{
szDest[i++] = 0xe0 + (0x0f & (num >> 12));
if(i >= nDest) break;
szDest[i++] = 0x80 + (0x3f & (num >> 6));
if(i >= nDest) break;
szDest[i++] = 0x80 + (0x3f & num);
}
else if(num > 0x0000ffff && num <= 0x0010ffff)//4 bytes
{
szDest[i++] = 0xf0 + (0x07 & (num >> 18));
if(i >= nDest) break;
szDest[i++] = 0x80 + (0x3f & (num >> 12));
if(i >= nDest) break;
szDest[i++] = 0x80 + (0x3f & (num >> 6));
if(i >= nDest) break;
szDest[i++] = 0x80 + (0x3f & num);
}
if(i >= nDest) break;
}
return i;
}


int UTF8ToUnicode(const char* szSrc, int nSrc, wchar_t* szDest, int nDest)
{
int iIndex = 0, iLen = 0;
while(iIndex < nSrc && iLen <= nDest)
{
int i = 7, num;
while((szSrc[iIndex] >> i) & 1)
i--;
i < 7 ? i++ : i;
num = 8 - i;
switch(num)//bytes count
{
case 1:
szDest[iLen] = szSrc[iIndex];
break;
case 2:
szDest[iLen] = ((0x1f & szSrc[iIndex]) << 6) + (0x3f & szSrc[iIndex + 1]);//bigendian
break;
case 3:
szDest[iLen] = ((0x0f & szSrc[iIndex]) << 12) + ((0x3f & szSrc[iIndex + 1]) << 6) + (0x3f & szSrc[iIndex + 2]);
break;
case 4:
szDest[iLen] = ((0x0f & szSrc[iIndex]) << 18) + ((0x3f & szSrc[iIndex + 1]) << 12) + ((0x3f & szSrc[iIndex + 2]) << 6) + (0x3f & szSrc[iIndex + 3]);
break;
default:
break;
}
iIndex += num;
iLen++;
}
return iLen;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值