移动开发中的字符集转换问题
在手机开发中会碰到关于字符类型的转换问题,特别是如果想在程序中支持中文则必须搞清楚某些字符集的表示方法,较常见的是UCS2、UTF-8、ASCII字符集,对于GB2312码则较少平台支持,所以往往要做的转换是把GB2312码转换成UCS2或UTF-8码。
1.UCS2
UCS2码是用两个字节表示一个字符,如果字符是ASCII码中的字符,则一个字节为空(值为0),另一个字节为原ASCII码的值。UCS2字符中的两个字节有个字节顺序的问题,不同平台中两个字节的顺序也许是相反的,所以在把UCS2字符转换成其它字符时,要先弄清楚字节顺序,否则转换出来的字符很有可能是乱码。
UCS2àASCII:要把UCS2转换成ASCII码,只要把其中为0的字节去掉就可以了。
UCS2àUTF-8:UCS2和UTF-8字符有一定的必然关系,所以转换有一个固定的方法,实现方法如下面的代码所示:(在windows CE中可以调用WideCharToMultiByte来实现,其中第一个参数设为CP_UTF8)
char * UCS2toUTF8(char *str,unsigned long len)
{
unsigned long res,i;
char *p,*q,*utf8 = NULL;
if(str==0) return 0;
p=str;
res=0;
q=(char*)malloc(len*3+1);
if(q==NULL)
return NULL;
if(q)
utf8=q;
p=str;
for(i=0;i
{
if((*p&#61;&#61;0x00)&&(*(p&#43;1)<0xa0))
{
*q&#43;&#43;&#61;*(p&#43;1);
p&#43;&#61;2;
}
else if(*p<0x08)
{
*q&#43;&#43;&#61;(char)(0xC0 | (char)(*p<<2) | (char)(*(p&#43;1)>>6));
*q&#43;&#43;&#61;(char)(0x80 | *(p&#43;1) & 0x3F);
p&#43;&#61;2;
}else
{
*q&#43;&#43;&#61;(char)(0xE0 | (char)(*p>>4));
*q&#43;&#43;&#61;(char)(0x80 | (char)((*p & 0x0F)<<2) | (char)(*(p&#43;1)>>6));
*q&#43;&#43;&#61;(char)(0x80 | *(p&#43;1) & 0x3F);
p&#43;&#61;2;
}
}
*q&#61;&#39;/0&#39;;
return utf8;
}
UCS2àGB2312:要把UCS2字符转换成GB2312字符并不是一件容易的事&#xff0c;因为二者之间没有固定的对应关系&#xff0c;必须根据映射表来进行转换&#xff0c;所以系统平台如果没有提供转换方法而要自己去实现则是件很麻烦的事&#xff1a;你要自己建立一张映射表&#xff0c;然后实现在映射表中查找。在windows CE中可以调用WideCharToMultiByte函数来实现(其中第一个参数值必须是936)。
2&#xff0e;UTF-8
UTF-8字符由一个以上的字节组成&#xff0c;其中可以根据第一个字节来判断该字符的长度&#xff1a;第一个字节中高位连续几个值为1的个数即表示该字符有多少个字节&#xff0c;如果是由两个以上的字节组成&#xff0c;则第二个字节以后的所有字节高两位都是“10”。ASCII码和UTF-8字符表示形式是一样的&#xff0c;所以二者之间可以不用进行特殊转换。UTF-8字符的一个优势是没有字节顺序&#xff0c;不象UCS2有字节顺序之分&#xff0c;所以很多平台采用了UTF-8字符来表示&#xff0c;其实UTF-8在网络通信中是最常用的。
UTF-8àUCS2&#xff1a;只要把UTF-8字符中表示字节个数的1和紧随其后的0去掉&#xff0c;以及后面字节头两位的“10”去掉&#xff0c;最后重新合并剩下的位&#xff0c;组合起来就是UCS2字符了&#xff0c;当然&#xff0c;如果UTF-8字符是ASCII码&#xff0c;则处理方法是不一样的&#xff1a;要加个空字节。处理方法如下面的代码&#xff1a;(在windows CE中可以调用MultiByteToWideChar来实现&#xff0c;其中第一个参数设为CP_UTF8)
char * UTF8toUCS2(char *str,unsigned long *len)
{
unsigned long res,i;
char *p,*q,*ucs2 &#61; NULL;
if(str&#61;&#61;0) return 0;
p&#61;str;
res&#61;0;
q&#61;(char*)malloc(*len*2&#43;1);
if(q&#61;&#61;NULL)
return NULL;
if(q) ucs2&#61;q;
p&#61;str;
for(i&#61;0;i<*len;)
{
if(*p<0xa0)
{
*q&#43;&#43;&#61;0x00;
*q&#43;&#43;&#61;*p&#43;&#43;;
i&#43;&#43;;
}
else if(*p<0xe0)
{
*q&#43;&#43;&#61;(char)(*p>>2 & 0x07);
*q&#43;&#43;&#61;(char)(*p<<6|(*(p&#43;1)&0x3f));
p&#43;&#61;2;
i&#43;&#61;2;
}else
{
*q&#43;&#43;&#61;(char)(*p<<4|(char)(*(p&#43;1)>>2)&0x0f);
*q&#43;&#43;&#61;(char)(*(p&#43;1)<<6|(*(p&#43;2)&0x3f));
p&#43;&#61;3;
i&#43;&#61;3;
}
}
if(len !&#61; NULL)
*len&#61;(unsigned long)(q-ucs2);
return ucs2;
}
UTF-8àGB2312&#xff1a;同UCS2一样&#xff0c;没有直接的对应关系&#xff0c;大部分平台没有提供二者之间的直接转换方法&#xff0c;必须先把UTF-8转换成UCS2字符&#xff0c;然后再把UCS2字符转换成GB2312字符&#xff0c;反过来要把GB2312字符转换成UTF-8字符&#xff0c;也是要先转换成UCS2字符。
3&#xff0e;ASCII
这个是在程序中最常用的也是最简单的字符&#xff0c;判断一个字符是否是ASCII码方法非常简单&#xff1a;只要看字节中最高位值是否为0&#xff0c;若为0则是ASCII码。ASCII码跟UCS2和UTF-8之间的转换方法可以看上面关于UCS2和UTF-8的描述。