字符集Unicode与UTF-8之间的转换
字符编码(1)——Unicode,utf-8
字符编码(1)——Unicode,utf-8字符编码编码是⼀个将⼀组Unicode字符转换业个字节序列的过程。
⽽解码是将⼀个编码字节序列转换为⼀组Unicode字符的过程。
Unicode字符是什么?Unicode字符集可以简写为UCS,也就是Unicode charactor setUnicode编码是国际组织制定的可以容纳世界上所有⽂字和符号的字符编码⽅案。
它通过0到0x10FFFF来映射字符,最多可容纳1114112个字符(16进制的10FFFF的值是1114111,然后加⼀个0x000000就是1114112个)。
可以看⼀下1114112的⼆进制表⽰形式为:1 0001 00000000 00000000UTF是什么?UTF是Unicode转换格式的意思,是UCS Transformation Format的缩写。
Utf-8UTF-8以字节为单位对Unicode进⾏编码。
utf-8特点是对不同范围的字符⽤不同长度的编码。
从Unicode到UTF-8的编码⽅式如下:Unicode编码(16进制) ║ UTF-8 字节流(⼆进制)000000 - 00007F ║ 0xxxxxxx000080 - 0007FF ║ 110xxxxx 10xxxxxx000800 - 00FFFF ║ 1110xxxx 10xxxxxx 10xxxxxx010000 - 10FFFF ║ 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx例如:“赵”这个字的Unicode编码(16进制表⽰⽅法)是:8d 75这个编码在.net中可以通过ToString()⽅法来实现。
为了进⾏后边的说明。
这⾥先给出测试⽤的转换⽅法:public static class CharSetHelper{public static string TransCoding(this int iValue,eTrans eType){return Convert.ToString(iValue, (int)eType);}public static string GetCorrectCoding(this string selfChar, Encoding encoding, eTrans eType){int iUnicode = (int)char.Parse(selfChar);return iUnicode.TransCoding(eType);}}public enum eTrans{Binary=2,Octonary=8,Decimal=10,Hexadecimal=16}⼀个枚举,⽤于枚举数的进制,⼀个从字串转换到特定的字符编码,并以指定进制表⽰的⽅法。
Python的ASCII,GB2312,Unicode,UTF-8相互转换
Python的ASCII,GB2312,Unicode,UTF-8相互转换ASCII 是⼀种字符集,包括⼤⼩写的英⽂字母、数字、控制字符等,它⽤⼀个字节表⽰,范围是 0-127 Unicode分为UTF-8和UTF-16。
UTF-8变长度的,最多 6 个字节,⼩于 127 的字符⽤⼀个字节表⽰,与 ASCII 字符集的结果⼀样,ASCII 编码下的英语⽂本不需要修改就可以当作 UTF-8 编码进⾏处理。
Python 从 2.2 开始⽀持 Unicode ,函数 decode( char_set )可以实现其它编码到 Unicode 的转换,函数 encode( char_set )实现 Unicode 到其它编码⽅式的转换。
⽐如("你好").decode( "GB2312")将得到u'\u4f60\u597d',即 "你"和“好"的 Unicode 码分别是 0x4f60 和 0x597d再⽤(u'\u4f60\u597d').encode("UTF-8")将得到'\xe4\xbd\xa0\xe5\xa5\xbd'它是 “你好”的UTF-8编码结果。
python中使⽤ unicode的关键:unicode是⼀个类,函数unicode(str,"utf8")从utf8编码(当然也可以是别的编码)的字符串str⽣成 unicode类的对象,⽽函数unc.encode("utf8")将unicode类的对象unc转换为(编码为)utf8编码(当然也可以是别的编码)的字符串。
于是,编写unicode相关程序,需要做的事情是 * 获取数据(字符串)时,⽤unicode(str, "utf8")⽣成unicode对象 * 在程序中仅使⽤unicode对象,对程序中出现的字符串常量都以u"字符串"的形式书写 * 输出时,可将unicode对象转换为任意编码输出,使⽤str.encode("some_encoding")>>> unicode("你好", "utf8")u'\u4f60\u597d'>>> x = _>>> type(x)>>> type("你好")>>> x.encode("utf8")'\xe4\xbd\xa0\xe5\xa5\xbd'>>> x.encode("gbk")'\xc4\xe3\xba\xc3'>>> x.encode("gb2312")'\xc4\xe3\xba\xc3'>>> print x你好>>> print x.encode("utf8")你好>>> print x.encode("gbk")以上是测试结果(Ubuntu 6.06,locale为utf8),注意type(x)和type("你好")的区别。
几个多字节和UNICODE及UTF-8之间相互转化的函数
几个多字节和UNICODE及UTF-8之间相互转化的函数做vc++开发免不了多字节UNICODE、UTF-8转来转去,下面贴出我写的几个字符转化函数1、TCHAR 和CHAR转化, TCHAR 对应UNICODE和多字节下分别是WCHAR 和CHAR 函数如下:需要注意*dest是new出来的需要释放//char 字符串转化为tchar字符串void C2T(TCHAR** dest, const char* src){#ifdef _UNICODEif (src == NULL){return ;}size_t alen = strlen(src) + 1;size_t ulen = (size_t)MultiByteToWideChar(CP_ACP, 0, src,ale n,NULL, 0 )+1;*dest = new WCHAR[ulen];::MultiByteToWideChar(CP_ACP, 0, src, alen, *dest, ulen);#else//多字节TCHAR就是charint len = strlen(src)+1;*dest = new char[len];strcpy(*dest, src);#endif}2、TCHAR转化为多字节,同样要注意*dest指针释放void T2C(char** dest, const TCHAR* src){if(src == NULL)return ;#ifdef _UNICODEsize_t len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0 , NULL, NULL);if (len == 0){return;}*dest = new char[len];WideCharT oMultiByte( CP_ACP, 0, src, -1, *dest, len, NULL, NULL );#elseint len = _tcslen(src) + 1;*dest = new TCHAR[len];strcpy(*dest, src);#endif}3、下面两个函数跟上面的有点重复但是后面会用到,也贴出来//多字节转化为宽字节void C2W(WCHAR** dest, const char* src){if (src == NULL)return ;}size_t alen = strlen(src) + 1;size_t ulen = (size_t)MultiByteToWideChar(CP_ACP, 0, src,ale n,NULL, 0 )+1;*dest = new WCHAR[ulen];::MultiByteToWideChar(CP_ACP, 0, src, alen, *dest, ulen);}//宽字节转化为多字节void W2C(char** dest, const WCHAR *src){if(src == NULL)return ;size_t len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0 , NULL, NULL);if (len == 0){return;}*dest = new char[len];WideCharT oMultiByte( CP_ACP, 0, src, -1, *dest, len, NULL, NULL );}4、UTF-8和多字节及宽字节之间的转化//UNICODE可以直接转化为UTF-8void UnicodeToUtf8(char** dest , const WCHAR* src){ASSERT(dest!= NULL || src != NULL);int len = -1;len = WideCharToMultiByte(CP_UTF8, 0, src, -1, 0, 0, 0, 0)+1; *dest = new char[len+1];::WideCharToMultiByte(CP_UTF8, 0, src, -1,*dest, len, 0, 0); }//多字节要先转化为宽字节在转化为UTF-8void AnsiT oUtf8(char** dest, const char* src){ASSERT(dest!= NULL || src != NULL);WCHAR* pwszStr = NULL;C2W(&pwszStr, src);UnicodeToUtf8(dest, pwszStr);SAFE_ARRYDELETE(pwszStr);}UTF-8转化为多字节或者UNICODE:void Utf8ToAnsi(char** dest, const char* src){ASSERT(dest!= NULL || src != NULL);WCHAR* str = NULL;Utf8ToUnicode(&str, src);W2C(dest, str);SAFE_ARRYDELETE(str);void Utf8ToUnicode(WCHAR** dest,const char* src){ASSERT(dest!= NULL || src != NULL);int unicodeLen = ::MultiByteToWideChar( CP_UTF8, 0, src, -1, NULL, 0 ) + 1;*dest = new WCHAR[unicodeLen];//memset(*dest, 0x0, (unicodeLen + 1)*sizeof(WCHAR));MultiByteToWideChar(CP_UTF8, 0, src, -1, *dest, unicodeLen);}SAFE_ARRYDELETE是一个内存是释放宏如下#define SAFE_ARRYDELETE(x) if(NULL!=x){delete[] x;x = NUL L;}#define SAFE_DELETE(x) if(NULL!=x){delete x; x =NULL;}有了以上函数基本上不同编码间可以随意转,大家也还可以对以上这些函数尽心扩展,需要注意的是上面这些函数中dest指向的指针需要释放。
VC下UNICOD和UTF8相互转换
Vc下unicode和UTF8相互转换在vc下使用SQLite数据库时,由于SQL语句使用utf8 编码,而CString 是unicode编码。
一, utf8 转UnicodeCString UTF8ToUnicode(char* UTF8){DWORD dwUnicodeLen; //转换后Unicode的长度TCHAR *pwText; //保存Unicode的指针CString strUnicode; //返回值//获得转换后的长度,并分配内存dwUnicodeLen = MultiByteToWideChar(CP_UTF8,0,UTF8,-1,NULL,0); pwText = new TCHAR[dwUnicodeLen];if (!pwText){return strUnicode;}//转为UnicodeMultiByteToWideChar(CP_UTF8,0,UTF8,-1,pwText,dwUnicodeLen);//转为CStringstrUnicode.Format(_T("%s"),pwText);//清除内存delete []pwText;//返回转换好的Unicode字串}二, Unicode转utf8size_t CDGQDialog::g_f_wctou8(char * dest_str, const wchar_t src_wchar){int count_bytes = 0;wchar_t byte_one = 0, byte_other = 0x3f; // 用于位与运算以提取位值0x3f--->00111111 unsigned char utf_one = 0, utf_other = 0x80; // 用于"位或"置标UTF-8编码0x80--->1000000 wchar_t tmp_wchar =L'0'; // 用于宽字符位置析取和位移(右移位)unsigned char tmp_char =L'0';if (!src_wchar)//return (size_t)-1;for (;;) // 检测字节序列长度{if (src_wchar <= 0x7f){ // <=01111111count_bytes = 1; // ASCII字符: 0xxxxxxx( ~ 01111111)byte_one = 0x7f; // 用于位与运算, 提取有效位值, 下同utf_one = 0x0;break;}if ( (src_wchar > 0x7f) && (src_wchar <= 0x7ff) ){ // <=0111,11111111count_bytes = 2; // 110xxxxx 10xxxxxx[1](最多个位, 简写为*1)byte_one = 0x1f; // 00011111, 下类推(1位的数量递减)break;}if ( (src_wchar > 0x7ff) && (src_wchar <= 0xffff) ){ //0111,11111111<=11111111,11111111 count_bytes = 3; // 1110xxxx 10xxxxxx[2](MaxBits: 16*1)byte_one = 0xf; // 00001111utf_one = 0xe0; // 11100000break;}if ( (src_wchar > 0xffff) && (src_wchar <= 0x1fffff) ){ //对UCS-4的支持..count_bytes = 4; // 11110xxx 10xxxxxx[3](MaxBits: 21*1)byte_one = 0x7; // 00000111utf_one = 0xf0; // 11110000break;}if ( (src_wchar > 0x1fffff) && (src_wchar <= 0x3ffffff) ){count_bytes = 5; // 111110xx 10xxxxxx[4](MaxBits: 26*1)byte_one = 0x3; // 00000011utf_one = 0xf8; // 11111000break;}if ( (src_wchar > 0x3ffffff) && (src_wchar <= 0x7fffffff) ){count_bytes = 6; // 1111110x 10xxxxxx[5](MaxBits: 31*1)utf_one = 0xfc; // 11111100break;}return (size_t)-1; // 以上皆不满足则为非法序列}// 以下几行析取宽字节中的相应位, 并分组为UTF-8编码的各个字节tmp_wchar = src_wchar;for (int i = count_bytes; i > 1; i--){ // 一个宽字符的多字节降序赋值tmp_char = (unsigned char)(tmp_wchar & byte_other);///后位与byte_other 00111111 dest_str[i - 1] = (tmp_char | utf_other);/// 在前面加----跟或tmp_wchar >>= 6;//右移位}//这个时候i=1//对UTF-8第一个字节位处理,//第一个字节的开头"1"的数目就是整个串中字节的数目tmp_char = (unsigned char)(tmp_wchar & byte_one);//根据上面附值得来,有效位个数dest_str[0] = (tmp_char | utf_one);//根据上面附值得来1的个数// 位值析取分组__End!return count_bytes;}int CDGQDialog::g_f_wcs_to_pchar(CString& wstr,char * p)wchar_t wc=L'1';char c[10]="1";//申请一个缓存size_t r=0; //size_t unsigned integer Result of sizeof operator int i=0;int j=0;for(i=0;i<wstr.GetLength();i++){wc=wstr.GetAt(i);//得到一个宽字符r=g_f_wctou8(c,wc);//将一个宽字符按UTF-8格式转换到p地址if(r==-1)//出错判断AfxMessageBox(_T("wcs_to_pchar error"));p[j]=c[0];//第一个值附给pj++;if(r>1){for(size_t x=1;x<r;x++){p[j]=c[x];j++;}}}return 1;}三.转换实例void CMytestDlg::OnBnClickedButton2(){// TODO: 在此添加控件通知处理程序代码CString ccId=L"2007071王";CString sql;char mySql[100];memset(mySql,0,sizeof(mySql));sql.Format(L"select cxrq,cxdw,dxrq,dxdw,fxrq,fxdw,cx,flx from j_clxx where trainnum_info_id ='%s'",ccId); //wchar_t sql=L'你';g_f_wcs_to_pchar(sql,mySql);CString sql1 =UTF8ToUnicode(mySql);MessageBox(sql);//g_f_wctou8(mySql,sql);// CString str_temp;// for (int i=90;i<strlen(mySql);i++)// {// str_temp.Format(L"%c",mySql[i]);// MessageBox(str_temp);// }。
PHP如何实现Unicode和Utf-8编码相互转换(2)
}
/**
* Unicode字符转换成utf8字符
* @param [type] $unicode_str Unicode字符
* @return [type] Utf-8字符
*/
function unicode_to_utf8($unicode_str) {
//这是汉字“你”的Uniቤተ መጻሕፍቲ ባይዱode编码
$unicode_str = '4f6b';
//输出 6211
echo utf8_str_to_unicode($utf8_str) . "<br/>";
//输出汉字“你”
echo unicode_str_to_utf8($unicode_str);
以上这些转换是针对中文汉字(非ASCII)的测试,并且只支持单个字符【一个完整的utf8字符或是一个完整的Unicode字符】互相转换,希望对大家的学习有所帮助。
以上这些转换是针对中文汉字非ascii的测试并且只支持单个字符一个完整的utf8字符或是一个完整的unicode字符互相转换希望对大家的学习有所帮助
PHP如何实现Unicode和Utf-8编码相互转换(2)
PHP如何实现Unicode和Utf-8编码相互转换
$unicode |= (ord($utf8_str[2]) & 0x3F);
$ord_3 = decbin(0x80 | ($code & 0x3f));
$utf8_str = chr(bindec($ord_1)) . chr(bindec($ord_2)) . chr(bindec($ord_3));
utf-8到unicode的编码转换
UTF-8到Unicode的编码转换UTF-8就是Unicode Transformation Format-8,是Unicode的一种变换编码格式。
UTF-8 有以下特性:UCS 字符 U+0000 到 U+007F (ASCII) 被编码为字节 0x00 到 0x7F (ASCII 兼容). 这意味着只包含 7 位 ASCII 字符的文件在 ASCII 和 UTF-8 两种编码方式下是一样的.所有 >U+007F 的 UCS 字符被编码为一个多个字节的串, 每个字节都有标记位集. 因此, ASCII 字节 (0x00-0x7F) 不可能作为任何其他字符的一部分.表示非 ASCII 字符的多字节串的第一个字节总是在 0xC0 到 0xFD 的范围里, 并指出这个字符包含多少个字节. 多字节串的其余字节都在 0x80 到 0xBF 范围里. 这使得重新同步非常容易, 并使编码无国界, 且很少受丢失字节的影响.可以编入所有可能的 231个 UCS 代码UTF-8 编码字符理论上可以最多到 6 个字节长, 然而 16 位 BMP 字符最多只用到 3 字节长.Bigendian UCS-4 字节串的排列顺序是预定的.字节 0xFE 和 0xFF 在 UTF-8 编码中从未用到.下列字节串用来表示一个字符. 用到哪个串取决于该字符在 Unicode 中的序号.U-00000000 - U-0000007F: 0xxxxxxxU-00000080 - U-000007FF: 110xxxxx 10xxxxxxU-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxxU-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxxU-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxxU-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx从上表还可以看出,UTF-8每个编码字符都不可能以“10”开头,“10”是以连接符的形式出现在后面的编码字节开头。
Unicode32和UTF8转换c源码
UCS32和UTF-8之间的C源码转换Sunny.man名词解释Big_Endia和little_Endia如果0x1234在内存BYTE buf[2]里面.buf[0]=0x34,buf[1]=0x12就是little_EnDian.如果buf[0]=0x12,buf[1]=0x34就是big_Endian。
如果用BOM(BYTE Order MASK)来标记FE FF就是大端.FF FE就是小端。
如果是EF BB BF就是utf-8。
在硬盘或是网络中传输时,没有大端小端,因为全是按字节来写或是来传的。
当读到内存中时就需要注意了。
我所举的例子全是小端模式。
也就是说0x594e在我的计算机里代表”奎”这个字。
好了不多说现在上源码。
unsigned long GetUTF32Len(unsigned char *input){unsigned long len=1;unsigned char test=*input;if(test>=0xC0) len++;if(test>=0xE0) len++;if(test>=0xF0) len++;if(test>=0xF8) len++;if(test>=0xFC) len++;return len;}unsigned long ConvertUTF8ToUTF32(unsigned char * input, int &length){const unsigned long FIRST_BYTE_MARK[7] = { 0x00,0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };const unsigned long MASK=0x80;//10 000000unsigned long len=GetUTF32Len(input);assert(!(len>length || len>6));unsigned long temp=*input++;unsigned long res=temp^FIRST_BYTE_MARK[len];for(int i=1;i<len;i++){temp=*input++;res=(res<<6)+(temp^MASK);}length-=len;return res;}void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ){const unsigned long BYTE_MASK = 0xBF;//1011 1111const unsigned long BYTE_MARK = 0x80;//1000 0000//1100 0000 1110 0000 1111 0000 1111 1000 1111 1100const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };if (input < 0x80)*length = 1;else if ( input < 0x800 )*length = 2;else if ( input < 0x10000 )*length = 3;else if ( input < 0x200000 )*length = 4;else{ *length = 0; return; } // This code won't covert this correctly anyway.output += *length;// Scary scary fall throughs.switch (*length){case 4:--output;*output = (char)((input | BYTE_MARK) & BYTE_MASK);input >>= 6;case 3:--output;*output = (char)((input | BYTE_MARK) & BYTE_MASK);input >>= 6;case 2:--output;*output = (char)((input | BYTE_MARK) & BYTE_MASK);input >>= 6;case 1:--output;*output = (char)(input | FIRST_BYTE_MARK[*length]);}}。
Ansi、Unicode、UTF8等编码字符串之间的转换和写入文本文件(学习中……)
Ansi、Unicode、UTF8等编码字符串之间的转换和写⼊⽂本⽂件(学习中……)最近有⼈问我关于这个的问题,就此写⼀篇blogAnsi 字符串我们最熟悉,英⽂占⼀个字节,汉字2个字节,以⼀个/0结尾,常⽤于txt⽂本⽂件Unicode 字符串,每个字符(汉字、英⽂字母)都占2个字节,以2个连续的/0结尾,NT操作系统内核⽤的是这种字符串,常被定义为typedef unsigned short wchar_t;所以我们有时常会见到什么char*⽆法转换为unsigned short*之类的错误,其实就是unicodeUTF8 是Unicode⼀种压缩形式,英⽂A在unicode中表⽰为0x0041,⽼外觉得这种存储⽅式太浪费,因为浪费了50%的空间,于是就把英⽂压缩成1个字节,成了utf8编码,但是汉字在utf8中占3个字节,显然⽤做中⽂不如ansi合算,这就是中国的⽹页⽤作ansi编码⽽⽼外的⽹页常⽤utf8的原因。
UTF8在还游戏⾥运⽤的很⼴泛,⽐如WOW的lua脚本等下⾯来说⼀下转换,主要⽤代码来说明吧写⽂件我⽤了CFile类,其实⽤FILE*之类的也是⼀样,写⽂件和字符串什么类别没有关系,硬件只关⼼数据和长度Ansi转Unicode介绍2种⽅法void CConvertDlg::OnBnClickedButtonAnsiToUnicode(){//ansitounicodechar*szAnsi="abcd1234你我他";//预转换,得到所需空间的⼤⼩int wcsLen=::MultiByteToWideChar(CP_ACP,NULL,szAnsi,strlen(szAnsi),NULL,0);//分配空间要给'/0'留个空间,MultiByteToWideChar不会给'/0'空间wchar_t*wszString=new wchar_t[wcsLen+1];//转换::MultiByteToWideChar(CP_ACP,NULL,szAnsi,strlen(szAnsi),wszString,wcsLen);//最后加上'/0'wszString[wcsLen]='/0';//unicode版的MessageBoxAPI::MessageBoxW(GetSafeHwnd(),wszString,wszString,MB_OK);//接下来写⼊⽂本//写⽂本⽂件,头2个字节0xfeff,低位0xff写在前CFilecFile;cFile.Open(_T("1.txt"),CFile::modeWrite|CFile::modeCreate);//⽂件开头cFile.SeekToBegin();cFile.Write("/xff/xfe",2);//写⼊内容cFile.Write(wszString,wcsLen*sizeof(wchar_t));cFile.Flush();cFile.Close();delete[]wszString;wszString=NULL;//⽅法2//设置当前地域信息,不设置的话,使⽤这种⽅法,中⽂不会正确显⽰//需要#include<locale.h>setlocale(LC_CTYPE,"chs");wchar_twcsStr[100];//注意下⾯是⼤写S,在unicode中,代表后⾯是ansi字符串//swprintf是sprintf的unicode版本//格式的前⾯要加⼤写L,代表是unicodeswprintf(wcsStr,L"%S",szAnsi);::MessageBoxW(GetSafeHwnd(),wcsStr,wcsStr,MB_OK);}Unicode转Ansi也是2种⽅法void CConvertDlg::OnBnClickedButtonUnicodeToAnsi(){//unicodetoansiwchar_t*wszString=L"abcd1234你我他";//预转换,得到所需空间的⼤⼩,这次⽤的函数和上⾯名字相反int ansiLen=::WideCharToMultiByte(CP_ACP,NULL,wszString,wcslen(wszString),NULL,0,NULL,NULL); //同上,分配空间要给'/0'留个空间char*szAnsi=newchar[ansiLen+1];//转换//unicode版对应的strlen是wcslen::WideCharToMultiByte(CP_ACP,NULL,wszString,wcslen(wszString),szAnsi,ansiLen,NULL,NULL);//最后加上'/0'szAnsi[ansiLen]='/0';//Ansi版的MessageBoxAPI::MessageBoxA(GetSafeHwnd(),szAnsi,szAnsi,MB_OK);//接下来写⼊⽂本//写⽂本⽂件,ANSI⽂件没有BOMCFilecFile;cFile.Open(_T("1.txt"),CFile::modeWrite|CFile::modeCreate);//⽂件开头cFile.SeekToBegin();//写⼊内容cFile.Write(szAnsi,ansiLen*sizeof(char));cFile.Flush();cFile.Close();delete[]szAnsi;szAnsi=NULL;//⽅法2//和上⾯⼀样有另⼀种⽅法setlocale(LC_CTYPE,"chs");char szStr[100];//注意下⾯是⼤写,在ansi中,代表后⾯是unicode字符串//sprintfsprintf(szStr,"%S",wszString);::MessageBoxA(GetSafeHwnd(),szStr,szStr,MB_OK);}Unicode转UTF8void CConvertDlg::OnBnClickedButtonUnicodeToU8(){//unicodetoUTF8wchar_t*wszString=L"abcd1234你我他";//预转换,得到所需空间的⼤⼩,这次⽤的函数和上⾯名字相反int u8Len=::WideCharToMultiByte(CP_UTF8,NULL,wszString,wcslen(wszString),NULL,0,NULL,NULL); //同上,分配空间要给'/0'留个空间//UTF8虽然是Unicode的压缩形式,但也是多字节字符串,所以可以以char的形式保存char*szU8=newchar[u8Len+1];//转换//unicode版对应的strlen是wcslen::WideCharToMultiByte(CP_UTF8,NULL,wszString,wcslen(wszString),szU8,u8Len,NULL,NULL);//最后加上'/0'szU8[u8Len]='/0';//MessageBox不⽀持UTF8,所以只能写⽂件//接下来写⼊⽂本//写⽂本⽂件,UTF8的BOM是0xbfbbefCFilecFile;cFile.Open(_T("1.txt"),CFile::modeWrite|CFile::modeCreate);//⽂件开头cFile.SeekToBegin();//写BOM,同样低位写在前cFile.Write("/xef/xbb/xbf",3);//写⼊内容cFile.Write(szU8,u8Len*sizeof(char));cFile.Flush();cFile.Close();delete[]szU8;szU8=NULL;}UTF8转UNICODEvoid CConvertDlg::OnBnClickedButtonU8ToUnicode(){//UTF8toUnicode//由于中⽂直接复制过来会成乱码,编译器有时会报错,故采⽤16进制形式char*szU8="abcd1234/xe4/xbd/xa0/xe6/x88/x91/xe4/xbb/x96/x00";//预转换,得到所需空间的⼤⼩int wcsLen=::MultiByteToWideChar(CP_UTF8,NULL,szU8,strlen(szU8),NULL,0);//分配空间要给'/0'留个空间,MultiByteToWideChar不会给'/0'空间wchar_t*wszString=new wchar_t[wcsLen+1];//转换::MultiByteToWideChar(CP_UTF8,NULL,szU8,strlen(szU8),wszString,wcsLen);//最后加上'/0'wszString[wcsLen]='/0';//unicode版的MessageBoxAPI::MessageBoxW(GetSafeHwnd(),wszString,wszString,MB_OK);//写⽂本同ansitounicode}Ansi转换utf8和utf8转换Ansi就是上⾯2个的结合,把unicode作为中间量,进⾏2次转换即可=======================================================================转载声明:本⽂转⾃。
UTF-8,Unicode,GB2312格式串转换之C语言版
UTF-8,Unicode,GB2312格式串转换之C语言版UTF-8, Unicode, GB2312格式串转换之C语言版(申明:此文章属于原创,若转载请表明作者和原处链接)/* author: wu.jian (吴剑) English name: Sword/* date: 2007-12-13/* purpose: 知识共享这几天工作上碰到了UTF-8转GB2312的问题,而且是在嵌入式的环境下,没有API可用,查了很多网上的资料,大多调用VC或者linux下自带的接口。
在这里我将这两天的工作做个总结。
总的来说分为两大步(这里就不介绍基础知识了):一、UTF8 -> Unicode由于UTF8和Unicode存在着联系,所以不需要任何库就可以直接进行转换。
首先要看懂UTF8的编码格式:U-00000000 - U-0000007F: 0xxxxxxxU-00000080 - U-000007FF: 110xxxxx 10xxxxxxU-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxxU-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxxU-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxx xxx前面几个1就代表后面几个字节是属于一起的。
如果要解析一长串UTF8格式的字符串,这点就很有用了。
下面这个函数就是判断前面几个1的(这里有 define APP_PRINT printf,这样当release的时候将这个宏定义为空就行了,不需要一个一个去改,又方便重新调试):int GetUtf8ByteNumForWord(u8 firstCh){u8 temp = 0x80;int num = 0;while (temp & firstCh){num++;temp = (temp >> 1);}APP_PRINT("the num is: %d", num);return num;}利用这个函数可以得到字符串中那几个字节是一起的。
utf8转unicode的方法
utf8转unicode的方法UTF-8是一种用于编码Unicode字符的可变长度字符编码方案。
在计算机中,字符是以二进制形式存储,而不同的字符编码方案决定了字符对应的二进制值。
UTF-8编码方案是一种通用的字符编码,可以表示世界上几乎所有的字符。
UTF-8编码使用1到4个字节表示一个字符,根据字符的不同范围确定字节数。
UTF-8编码的规则如下:1. 对于单字节的字符,字节的第一位设为0,后面的7位表示字符的Unicode码。
2. 对于多字节的字符,首字节的前n位设为1,第n+1位设为0,后面的字节的前两位都设为10,剩下的位用于存储字符的Unicode 码。
UTF-8编码的优势在于兼容ASCII字符集。
ASCII字符集是最早的字符编码方案,只使用一个字节表示一个字符,其中前128个字符与UTF-8编码完全兼容。
这意味着ASCII字符集中的字符,可以直接使用UTF-8编码表示,不会增加额外的字节。
UTF-8编码的转换过程十分简单。
对于需要转换的字符,首先确定其Unicode码。
根据Unicode码的范围,确定字符所需的字节数。
然后,将Unicode码转换成对应的二进制形式,并按照UTF-8编码的规则确定每个字节的值。
最后,将每个字节的二进制值转换成十六进制形式,得到最终的UTF-8编码。
举例来说,我们将字符"你"转换成UTF-8编码。
首先,查找该字符的Unicode码为U+4F60。
根据Unicode码的范围,我们知道该字符需要3个字节进行编码。
接下来,将Unicode码转换成二进制形式,得到"100111001100000"。
根据UTF-8编码的规则,我们将这个二进制值划分为三个字节:10011100、10010000、10000000。
最后,将每个字节的二进制值转换成十六进制形式,得到最终的UTF-8编码为E4BDA0。
在计算机中,我们可以使用各种编程语言进行UTF-8到Unicode 的转换。
JS实现unicode和UTF-8之间的互相转换互转
JS实现unicode和UTF-8之间的互相转换互转有⼀设备,为短信⽹关。
需将PC送过来的UTF-8转换成UNICODE才能将内容通过短信发送出去,同样,接收到的短信为unicode编码,也许转换成UTF-8才能在PC端软件显⽰出来。
程序很简单,只是⾛了不少弯路://unicode为1个接收数据,串⼝收到的字符编码放在该数组中function UnicodeToUtf8(unicode) {var uchar;var utf8str = "";var i;for(i=0; i<unicode.length;i+=2){uchar = (unicode[i]<<8) | unicode[i+1]; //UNICODE为2字节编码,⼀次读⼊2个字节utf8str = utf8str + String.fromCharCode(uchar); //使⽤String.fromCharCode强制转换}return utf8str;}function Utf8ToUnicode(strUtf8) {var i,j;var uCode;var temp = new Array();for(i=0,j=0; i<strUtf8.length; i++){uCode = strUtf8.charCodeAt(i);if(uCode<0x100){ //ASCII字符temp[j++] = 0x00;temp[j++] = uCode;}else if(uCode<0x10000){temp[j++] = (uCode>>8)&0xff;temp[j++] = uCode&0xff;}else if(uCode<0x1000000){temp[j++] = (uCode>>16)&0xff;temp[j++] = (uCode>>8)&0xff;temp[j++] = uCode&0xff;}else if(uCode<0x100000000){temp[j++] = (uCode>>24)&0xff;temp[j++] = (uCode>>16)&0xff;temp[j++] = (uCode>>8)&0xff;temp[j++] = uCode&0xff;}else{break;}}temp.length = j;return temp;}以上所述是⼩编给⼤家介绍的JS实现unicode和UTF-8之间的互相转换互转,希望对⼤家有所帮助,如果⼤家有任何疑问请给我留⾔,⼩编会及时回复⼤家的。
多字节与UTF-8、Unicode之间的转换
多字节与UTF-8、Unicode之间的转换1.2.3.// 多字节编码转为UTF8编码4.bool MBToUTF8(vector<char>& pu8, const char* pmb, int32 mLen)5.{6.// convert an MBCS string to widechar7. int32 nLen = MultiByteToWideChar(CP_ACP, 0, pmb, mLen, NULL, 0);8.9.WCHAR* lpszW = NULL;10.try11. {12. lpszW = new WCHAR[nLen];13. }14.catch(bad_alloc &memExp)15. {16.return false;17. }18.19. int32 nRtn = MultiByteToWideChar(CP_ACP, 0, pmb, mLen, lpszW, nLen);20.21.if(nRtn != nLen)22. {23.delete[] lpszW;24.return false;25. }26.// convert an widechar string to utf827. int32 utf8Len = WideCharToMultiByte(CP_UTF8, 0, lpszW, nLen, NULL, 0, NULL, NULL);28.if (utf8Len <= 0)29. {30.return false;31. }32. pu8.resize(utf8Len);33. nRtn = WideCharToMultiByte(CP_UTF8, 0, lpszW, nLen, &*pu8.begin(), utf8Len, NULL, NULL);34.delete[] lpszW;35.36.if (nRtn != utf8Len)37. {38. pu8.clear();39.return false;41.return true;42.}43.44.// UTF8编码转为多字节编码45.bool UTF8ToMB(vector<char>& pmb, const char* pu8, int32 utf8Len)46.{47.// convert an UTF8 string to widechar48. int32 nLen = MultiByteToWideChar(CP_UTF8, 0, pu8, utf8Len, NULL, 0);49.50.WCHAR* lpszW = NULL;51.try52. {53. lpszW = new WCHAR[nLen];54. }55.catch(bad_alloc &memExp)56. {57.return false;58. }59.60. int32 nRtn = MultiByteToWideChar(CP_UTF8, 0, pu8, utf8Len, lpszW, nLen);61.62.if(nRtn != nLen)63. {64.delete[] lpszW;65.return false;66. }67.68.// convert an widechar string to Multibyte69. int32 MBLen = WideCharToMultiByte(CP_ACP, 0, lpszW, nLen, NULL, 0, NULL, NULL);70.if (MBLen <=0)71. {72.return false;73. }74. pmb.resize(MBLen);75. nRtn = WideCharToMultiByte(CP_ACP, 0, lpszW, nLen, &*pmb.begin(), MBLen, NULL, NULL);76.delete[] lpszW;77.78.if(nRtn != MBLen)79. {80. pmb.clear();81.return false;83.return true;84.}85.86.// 多字节编码转为Unicode编码87.bool MBToUnicode(vector<wchar_t>& pun, const char* pmb, int32 mLen)88.{89.// convert an MBCS string to widechar90. int32 uLen = MultiByteToWideChar(CP_ACP, 0, pmb, mLen, NULL, 0);91.92.if (uLen<=0)93. {94.return false;95. }96. pun.resize(uLen);97.98. int32 nRtn = MultiByteToWideChar(CP_ACP, 0, pmb, mLen, &*pun.begin(), uLen);99.100.if (nRtn != uLen)101. {102. pun.clear();103.return false;104. }105.return true;106.}107.108.//Unicode编码转为多字节编码109.bool UnicodeToMB(vector<char>& pmb, const wchar_t* pun, int32 uLen)110.{111.// convert an widechar string to Multibyte112. int32 MBLen = WideCharToMultiByte(CP_ACP, 0, pun, uLen, NULL, 0, NULL, NULL);113.if (MBLen <=0)114. {115.return false;116. }117. pmb.resize(MBLen);118.int nRtn = WideCharToMultiByte(CP_ACP, 0, pun, uLen, &*pmb.begin(), MBL en, NULL, NULL);119.120.if(nRtn != MBLen)121. {122. pmb.clear();124. }125.return true;126.}127.128.// UTF8编码转为Unicode129.bool UTF8ToUnicode(vector<wchar_t>& pun, const char* pu8, int32 utf8Len) 130.{131.// convert an UTF8 string to widechar132. int32 nLen = MultiByteToWideChar(CP_UTF8, 0, pu8, utf8Len, NULL, 0); 133.if (nLen <=0)134. {135.return false;136. }137. pun.resize(nLen);138. int32 nRtn = MultiByteToWideChar(CP_UTF8, 0, pu8, utf8Len, &*pun.begin( ), nLen);139.140.if(nRtn != nLen)141. {142. pun.clear();143.return false;144. }145.146.return true;147.}148.149.// Unicode编码转为UTF8150.bool UnicodeToUTF8(vector<char>& pu8, const wchar_t* pun, int32 uLen) 151.{152.// convert an widechar string to utf8153. int32 utf8Len = WideCharToMultiByte(CP_UTF8, 0, pun, uLen, NULL, 0, NUL L, NULL);154.if (utf8Len<=0)155. {156.return false;157. }158. pu8.resize(utf8Len);159. int32 nRtn = WideCharToMultiByte(CP_UTF8, 0, pun, uLen, &*pu8.begin(), utf8Len, NULL, NULL);160.161.if (nRtn != utf8Len)162. {163. pu8.clear();165. }166.return true;167.}Ansi字符串我们最熟悉,英文占一个字节,汉字2个字节,以一个\0结尾,常用于txt文本文件Unicode字符串,每个字符(汉字、英文字母)都占2个字节,以2个连续的\0结尾,NT操作系统内核用的是这种字符串,常被定义为typedef unsigned short wchar_t;所以我们有时常会见到什么char*无法转换为unsigned short*之类的错误,其实就是unicodeUTF8是Unicode一种压缩形式,英文A在unicode中表示为0x0041,老外觉得这种存储方式太浪费,因为浪费了50%的空间,于是就把英文压缩成1个字节,成了utf8编码,但是汉字在utf8中占3个字节,显然用做中文不如ansi合算,这就是中国的网页用作ansi 编码而老外的网页常用utf8的原因。
c++字符集之间转换(UTF-8,UNICODE,Gb2312)
j += 3;
i += 2;
}
}
rst[j] = ’’;
//返回结果
pOut = rst;
delete[]rst;
return;
}
voidCChineseCode::UTF_8ToGB2312(string &pOut, char*pText, intpLen){
return;
}
voidCChineseCode::UnicodeToGB2312(char* pOut,wchar_tuData){
WideCharToMultiByte(CP_ACP,NULULL,NULL);
return;
}
voidCChineseCode::Gb2312ToUnicode(wchar_t* pOut,char*gbBuffer){
}else{
wchar_tpbuffer;
Gb2312ToUnicode(&pbuffer,pText+i);
UnicodeToUTF_8(buf,&pbuffer);
unsigned shortinttmp = 0;
tmp = rst[j] = buf[0];
tmp = rst[j+1] = buf[1];
};
//类实现
voidCChineseCode::UTF_8ToUnicode(wchar_t* pOut,char*pText){
char* uchar = (char*)pOut;
uchar[1] = ((pText[0] & 0x0F) << 4) + ((pText[1] >> 2) & 0x0F);
Unicode和UTF-8之间的转换
Unicode和UTF-8之间的转换⼀、引⾔通过这⼏天的研究,终于明⽩了Unicode和UTF-8之间编码的区别。
Unicode是⼀个字符集,⽽UTF-8是Unicode的其中⼀种,Unicode是定长的都为双字节,⽽UTF-8是可变的,对于汉字来说Unicode占有的字节⽐UTF-8占⽤的字节少1个字节。
Unicode为双字节,⽽UTF-8中汉字占三个字节。
注: Unicode编码⽬前规划的总空间是17个平⾯,0x0000 ⾄ 0x10FFFF。
每个平⾯有 65536 个码点。
因此这个总的长度也有⼀百多万个。
⼆、UTF-8 UTF-8编码字符理论上可以最多到6个字节长,然⽽16位BMP(Basic Multilingual Plane)字符最多只⽤到3字节长。
下⾯看⼀下UTF-8编码表:1 U-00000000 - U-0000007F: 0xxxxxxx23 U-00000080 - U-000007FF: 110xxxxx 10xxxxxx45 U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx67 U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx89 U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx1011 U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx xxx 的位置由字符编码数的⼆进制表⽰的位填⼊,越靠右的 x 具有越少的特殊意义,只⽤最短的那个⾜够表达⼀个字符编码数的多字节串。
注意在多字节串中,第⼀个字节的开头"1"的数⽬就是整个串中字节的数⽬。
Unicode,ISO-8859-1,GBK,UTF-8编码及相互转换
第二篇:JAVA字符编码系列二:Unicode,ISO-8859-1,GBK,UTF-8编码及相互转换1、函数介绍在Java中,字符串用统一的Unicode编码,每个字符占用两个字节,与编码有关的两个主要函数为:1)将字符串用指定的编码集合解析成字节数组,完成Unicode-〉charsetName转换public byte[] getBytes(String charsetName) throwsUnsupportedEncodingException2)将字节数组以指定的编码集合构造成字符串,完成charsetName-〉Unicode转换public String(byte[] bytes, String charsetName) throwsUnsupportedEncodingException2、Unicode与各编码之间的直接转换下面以对中文字符串"a中文"的编码转换为例,来了解各种编码之间的转换1)Unicode和GBK测试结果如下,每个汉字转换为两个字节,且是可逆的,即通过字节可以转换回字符串String-GBK〉ByteArray:\u0061\u4E2D\u6587(a中文)-〉0x61 0xD6 0xD00xCE 0xC4ByteArray-GBK〉String:0x610xD60xD00xCE0xC4-〉\u0061\u4E2D\u6587(a中文)2)Unicode和UTF-8测试结果如下,每个汉字转换为三个字节,且是可逆的,即通过字节可以转换回字符串String-UTF-8〉ByteArray:\u0061\u4E2D\u6587(a中文)-〉0x610xE40xB80xAD 0xE6%0x96 0x87ByteArray-UTF-8〉String:0x61 0xE4 0xB8 0xAD 0xE6%0x96 0x87-〉\u0061\u4E2D\u6587(a中文)3)Unicode和ISO-8859-1测试结果如下,当存在汉字时转换失败,非可逆,即通过字节不能再转换回字符串String-ISO-8859-1〉ByteArray:\u0061\u4E2D\u6587(a中文)-〉0x610x3FByteArray-ISO-8859-1〉String:0x610x3F-〉\u0061\u003F\u003F(a??)3、Unicode与各编码之间的交叉转换在上面直接转换中,由字符串(Unicode)生成的字节数组,在构造回字符串时,使用的是正确的编码集合,如果使用的不是正确的编码集合会怎样呢?会正确构造吗?如果不能正确构造能有办法恢复吗?会信息丢失吗?下面我们就来看看这种情况,这部分可以说明在某些情况下虽然我们最终正确显示了结果,但其间仍然进行了不正确的转换。
Python3编码问题Unicodeutf-8bytes互转方法
Python3编码问题Unicodeutf-8bytes互转⽅法为什么需要本⽂,因为在对接某些很⽼的接⼝的时候,需要传递过去的是16进制的hex字符串,并且要求对传的字符串做编码,这⾥就介绍了utf-8 Unicode bytes 等等。
#英⽂使⽤utf-8 转换成16进制hex字符串的⽅法newstr = 'asd'b_str = bytes(newstr,encoding='utf-8')print(b_str)hex_str = b_str.hex() #将bytes类型转换成16进制的hex字符串print(hex_str) #字节码转16进制hex的⽅法print(bytes.fromhex(hex_str).decode('utf-8')) #将16进制hex字符串转换成bytes,然后在转换成字符串print(type('中⽂'.encode('utf-8')),'中⽂'.encode('unicode_escape'),'中⽂123456'.encode('unicode_escape').decode('utf-8'))#中⽂转换成Unicode的⼀种⽅法之⼀u_str = '中⽂123456'b_str = bytes(u_str,encoding='unicode_escape')h_u_s = b_str.hex()print ("\u4e2d\u6587") #Unicode编码可直接输出#中⽂使⽤Unicode转换成bytes再转换成16进制hex⽅法包含英⽂和数字u_cn = '中⽂asd123'hex_msg = bytes(u_cn,encoding='utf_16_be').hex()#这是特殊要求下最终的解决⽅案#注意在Python3中已经没有了直接将字符串变成bytes或者Unicode的⽅法了#也就是说,在Python中 u'中⽂'已经不再奏效#bytes转strb_str = bytes('中⽂',encoding='utf-8')print(b_str.decode()) #直接输出为普通字符串以上这篇Python3编码问题 Unicode utf-8 bytes互转⽅法就是⼩编分享给⼤家的全部内容了,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。
UNICODE与UTF-8的转换详解
UNICODE与UTF-8的转换详解UNICODE与UTF-8的转换详解1 编码在计算机中,各种信息都是以⼆进制编码的形式存在的,也就是说,不管是⽂字、图形、声⾳、动画,还是电影等各种信息,在计算机中都是以0和1组成的⼆进制代码表⽰的。
为了区分这些信息,⼈们就为计算机设计了⼀套识别准则,这也就是计算机编码。
例如:英⽂字母与汉字的的区别,就是英⽂字母⽤的是单字节的ASCII码,汉字采⽤的是双字节的汉字内码。
1.1 基本概念* 字符:字符是抽象的最⼩⽂本单位。
它没有固定的形状(可能是⼀个字形),⽽且没有值。
“A”是⼀个字符,“€”(德国、法国和许多其他欧洲国家通⽤货币的标志)也是⼀个字符。
* 字符集:字符集是字符的集合。
例如,汉字字符是中国⼈最先发明的字符,在中⽂、⽇⽂、韩⽂和越南⽂的书写中使⽤。
* 编码字符集:编码字符集是⼀个字符集,它为每⼀个字符分配⼀个唯⼀数字。
Unicode 标准的核⼼是⼀个编码字符集,字母“A”的编码为 004116 和字符“€”的编码为 20AC16。
Unicode 标准始终使⽤⼗六进制数字,⽽且在书写时在前⾯加上前缀“U+”,所以“A”的编码书写为“U+0041”。
* 代码点:代码点是指可⽤于编码字符集的数字。
编码字符集定义⼀个有效的代码点范围,但是并不⼀定将字符分配给所有这些代码点。
有效的Unicode代码点范围是 U+0000 ⾄U+10FFFF。
Unicode4.0将字符分配给⼀百多万个代码点中的96,382代码点。
* 增补字符:增补字符是代码点在 U+10000 ⾄ U+10FFFF 范围之间的字符,也就是那些使⽤原始的Unicode的16 位设计⽆法表⽰的字符。
从U+0000⾄U+FFFF之间的字符集有时候被称为基本多语⾔⾯ (BMP)。
因此,每⼀个Unicode 字符要么属于BMP,要么属于增补字符。
* 字符编码⽅案:字符编码⽅案是从⼀个或多个编码字符集到⼀个或多个固定宽度代码单元序列的映射。
GBK、UTF8、UNICODE编码转换
GBK、UTF8、UNICODE编码转换1 string GBKToUTF8(const std::string& strGBK)2 {3 int nLen = MultiByteToWideChar(CP_ACP, 0, strGBK.c_str(), -1, NULL, 0);4 WCHAR * wszUTF8 = new WCHAR[nLen];5 MultiByteToWideChar(CP_ACP, 0, strGBK.c_str(), -1, wszUTF8, nLen);67 nLen = WideCharToMultiByte(CP_UTF8, 0, wszUTF8, -1, NULL, 0, NULL, NULL);8 char * szUTF8 = new char[nLen];9 WideCharToMultiByte(CP_UTF8, 0, wszUTF8, -1, szUTF8, nLen, NULL, NULL);1011 std::string strTemp(szUTF8);12 delete[]wszUTF8;13 delete[]szUTF8;14 return strTemp;15 }1 string UTF8ToGBK(const std::string& strUTF8)2 {3 int nLen = MultiByteToWideChar(CP_UTF8, 0, strUTF8.c_str(), -1, NULL, 0);4 unsigned short * wszGBK = new unsigned short[nLen + 1];5 memset(wszGBK, 0, nLen * 2 + 2);6 MultiByteToWid 8 nLen = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)wszGBK, -1, NULL, 0, NULL, NULL); 9 char *szGBK = new char[nLen + 1];10 memset(szGBK, 0, nLen + 1);11 WideCharToMultiByte(CP_ACP,0, (LPWSTR)wszGBK, -1, szGBK, nLen, NULL, N 13 std::string strTemp(szGBK);14 delete[]szGBK;15 delete[]wszGBK;16 return strTemp;17 }1 std::string Gbk2Unicode(std::string &strValue)2 {3 std::string strReturn;4 unsigned char chTemp;5 int nLength = strValue.length()*4+1;6 WCHAR *pwchBuf = new WCHAR[nLength];7 memset(pwchBuf, 0, sizeof(WCHAR) * nLength); 89 MultiByteToWideChar(CP_ACP, 0, strValue.c_str(), -1, (LPWSTR)pwchBuf, nLength);1011 for (size_t i = 0; i < wcslen(pwchBuf); i++)12 {13 strReturn += "\\u";14 chTemp = *((unsigned char*)pwchBuf+i*2+1);15 if(chTemp)16 {17 strReturn += m_clsmyOpenssl.char_to_hex( (unsigned char)(chTemp >> 4) );18 1 std::string Unicode2GBK(std::string &strValue) 2 { 3 std::vector<std::string> vcString; 4 MyTools::SplitString(strValue, "\\u", vcString); 56 wchar_t* pwBuf = new wchar_t[strValue.length() + 1];7 memset(pwBuf, 0, (strValue.length() + 1)* sizeof(wchar_t)); 89 int j(0);1011 for(std::vector<std::string>::iterator it = vcString.begin(); it != vcString.end(); ++it)12 {13 if (it->empty())14 {15 continue;16 }17 unsigned short wcTmp = 0;18 unsigned char cTmp = 0;1920 //因为有中⽂字符混合ASSCII码情况,所以条件为k < it->length()21 for(size_t k = 0; k < it->length(); ++k)22 {23 cTmp = (unsigned char)(*it)[k];2425 if(cTmp <= '9')//0x30~0x39 即0~926 {27 wcTmp |= (cTmp & 0x0f) << (it->length() - k - 1) * 4;28 }29 else if(cTmp >= 'a')//0x61~7a 即a~z30 {31 wcTmp |= (cTmp - 0x57) << (it->length() - k - 1) * 4;32 }33 else//0x41~5a 即A~Z34 {35 wcTmp |= (cTmp - 0x37) << (it->length() - k - 1) * 4;36 }37 }38 pwBuf[j++] = (wchar_t)wcTmp;39 }40 char *pDst = new char[strValue.length() + 1];41 memset(pDst, 0, (strValue.length() + 1) * sizeof(char));42 43 WideCharToMultiByte(CP_ACP, 0, pwBuf, -1, (char*)pDst, strValue.length() - 1, NULL, NULL);44 std::string strRet(pDst);4546 delete[]pwBuf;47 pwBuf= NULL;4849 delete[]pDst;50 pDst=NULL;5152 return strRet;53 }。
Unicode与UTF-8互相转换(C语言实现)
Unicode与UTF-8互相转换(C语⾔实现)1. 基础1.1 ASCII码我们知道, 在计算机内部, 所有的信息最终都表⽰为⼀个⼆进制的字符串. 每⼀个⼆进制位(bit)有0和1两种状态, 因此⼋个⼆进制位就可以组合出 256种状态, 这被称为⼀个字节(byte). 也就是说, ⼀个字节⼀共可以⽤来表⽰256种不同的状态, 每⼀个状态对应⼀个符号, 就是256个符号, 从 0000000到11111111. 上个世纪60年代, 美国制定了⼀套字符编码, 对英语字符与⼆进制位之间的关系, 做了统⼀规定. 这被称为ASCII 码, ⼀直沿⽤⾄今.ASCII码⼀共规定了128个字符的编码, ⽐如空格"SPACE"是32(⼆进制00100000), ⼤写的字母A是65(⼆进制01000001). 这128个符号(包括32个不能打印出来的控制符号), 只占⽤了⼀个字节的后⾯7位, 最前⾯的1位统⼀规定为0.1.2 ⾮ASCII编码英语⽤128个符号编码就够了, 但是⽤来表⽰其他语⾔, 128个符号是不够的. ⽐如, 在法语中, 字母上⽅有注⾳符号, 它就⽆法⽤ASCII码表⽰. 于是, ⼀些欧洲国家就决定, 利⽤字节中闲置的最⾼位编⼊新的符号. ⽐如, 法语中的é的编码为130(⼆进制10000010). 这样⼀来, 这些欧洲国家使⽤的编码体系, 可以表⽰最多256个符号. 但是, 这⾥⼜出现了新的问题. 不同的国家有不同的字母, 因此, 哪怕它们都使⽤256个符号的编码⽅式, 代表的字母却不⼀样. ⽐如, 130在法语编码中代表了é, 在希伯来语编码中却代表了字母Gimel (ג), 在俄语编码中⼜会代表另⼀个符号.NOTE:但是不管怎样, 所有这些编码⽅式中, 0-127表⽰的符号是⼀样的, 不⼀样的只是128-255 的这⼀段. // MMMMM⾄于亚洲国家的⽂字, 使⽤的符号就更多了, 汉字就多达10万左右. ⼀个字节只能表⽰ 256种符号, 肯定是不够的, 就必须使⽤多个字节表达⼀个符号. ⽐如, 简体中⽂常见的编码⽅式是GB2312, 使⽤两个字节表⽰⼀个汉字, 所以理论上最多可以表⽰ 256x256=65536个符号.2. Unicode2.1 Unicode的定义正如上⼀节所说, 世界上存在着多种编码⽅式, 同⼀个⼆进制数字可以被解释成不同的符号. 因此, 要想打开⼀个⽂本⽂件, 就必须知道它的编码⽅式, 否则⽤错误的编码⽅式解读, 就会出现乱码. 为什么电⼦邮件常常出现乱码?就是因为发信⼈和收信⼈使⽤的编码⽅式不⼀样.可以想象, 如果有⼀种编码, 将世界上所有的符号都纳⼊其中. 每⼀个符号都给予⼀个独⼀⽆⼆的编码, 那么乱码问题就会消失. 这就是Unicode, 就像它的名字都表⽰的, 这是⼀种所有符号的编码.Unicode也是⼀种字符编码⽅法, 不过它是由国际组织设计, 可以容纳全世界所有语⾔⽂字的编码⽅案. Unicode的学名是"Universal Multiple-Octet Coded Character Set", 简称为UCS. UCS可以看作是"Unicode Character Set"的缩写.Unicode当然是⼀个很⼤的集合, 现在的规模可以容纳100多万个符号. 每个符号的编码都不⼀样, ⽐如, U+0639表⽰阿拉伯字母Ain,U+0041表⽰英语的⼤写字母A, U+4E25表⽰汉字"严". 具体的符号对应表, 可以查询, 或者专门的汉字对应表.2.2 Unicode的问题需要注意的是, "Unicode只是⼀个符号集, 它只规定了符号的⼆进制代码, 却没有规定这个⼆进制代码应该如何存储".⽐如, 汉字"严"的unicode是⼗六进制数4E25, 转换成⼆进制数⾜⾜有15位 (100111000100101), 也就是说这个符号的表⽰⾄少需要2个字节.表⽰其他更⼤的符号, 可能需要3个字节或者4个字节, 甚⾄更多.这⾥就有两个严重的问题, 第⼀个问题是, 如何才能区别unicode和ascii?计算机怎么知道三个字节表⽰⼀个符号, ⽽不是分别表⽰三个符号呢?第⼆个问题是, 我们已经知道, 英⽂字母只⽤⼀个字节表⽰就够了, 如果unicode统⼀规定, 每个符号⽤三个或四个字节表⽰, 那么每个英⽂字母前都必然有⼆到三个字节是0, 这对于存储来说是极⼤的浪费, ⽂本⽂件的⼤⼩会因此⼤出⼆三倍, 这是⽆法接受的. 它们造成的结果是:1) 出现了unicode的多种存储⽅式, 也就是说有许多种不同的⼆进制格式, 可以⽤来表⽰unicode.2) unicode在很长⼀段时间内⽆法推⼴, 直到互联⽹的出现3. UTF-8互联⽹的普及, 强烈要求出现⼀种统⼀的编码⽅式. UTF-8就是在互联⽹上使⽤最⼴的⼀种unicode的实现⽅式. 其他实现⽅式还包括UTF-16和UTF-32, 不过在互联⽹上基本不⽤. 重复⼀遍, 这⾥的关系是, UTF-8是Unicode的实现⽅式之⼀.UTF-8最⼤的⼀个特点, 就是它是⼀种变长的编码⽅式. 它可以使⽤1~6个字节表⽰⼀个符号, 根据不同的符号⽽变化字节长度.3.1 UTF-8的编码规则UTF-8的编码规则很简单, 只有两条:1) 对于单字节的符号, 字节的第⼀位设为0, 后⾯7位为这个符号的unicode码. 因此对于英语字母, UTF-8编码和ASCII码是相同的.2) 对于n字节的符号(n>1), 第⼀个字节的前n位都设为1, 第n+1位设为0, 后⾯字节的前两位⼀律设为10. 剩下的没有提及的⼆进制位, 全部为这个符号的unicode码.下表总结了编码规则, 字母x表⽰可⽤编码的位.| Unicode符号范围 | UTF-8编码⽅式n | (⼗六进制) | (⼆进制)---+-----------------------+------------------------------------------------------1 | 00000000 - 0000 007F | 0xxxxxxx2 | 00000080 - 0000 07FF | 110xxxxx 10xxxxxx3 | 00000800 - 0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx4 | 00010000 - 0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx5 | 00200000 - 03FF FFFF | 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx6 | 04000000 - 7FFF FFFF | 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx表1. UTF-8的编码规则下⾯, 还是以汉字"严"为例, 演⽰如何实现UTF-8编码.已知"严"的unicode是4E25(1001110 00100101), 根据上表, 可以发现4E25处在第三⾏的范围内(0000 0800 - 0000 FFFF), 因此"严"的UTF-8编码需要三个字节, 即格式是 "1110xxxx 10xxxxxx 10xxxxxx". 然后, 从"严"的最后⼀个⼆进制位开始, 依次从后向前填⼊格式中的x, 多出的位补0. 这样就得到了, "严"的UTF-8编码是 "111001001011100010100101", 转换成⼗六进制就是E4B8A5.4. Little endian和Big endian上⼀节已经提到, Unicode码可以采⽤UCS-2格式直接存储. 以汉字"严"为例, Unicode码是4E25, 需要⽤两个字节存储, ⼀个字节是4E, 另⼀个字节是25. 存储的时候, 4E在前, 25在后, 就是Big endian⽅式; 25在前, 4E在后, 就是Little endian⽅式.// Big Endian(4E25) Little Endian(254E)因此, 第⼀个字节在前, 就是"⼤头⽅式"(Big endian), 第⼆个字节在前就是"⼩头⽅式 "(Little endian).4.1 计算机怎么知道某⼀个⽂件到底采⽤哪⼀种⽅式编码?(零宽度⾮换⾏空格(FEFF))Unicode规范中定义, 每⼀个⽂件的最前⾯分别加⼊⼀个表⽰编码顺序的字符, 这个字符的名字叫做"零宽度⾮换⾏空格"(ZERO WIDTH NO-BREAK SPACE), ⽤FEFF表⽰. 这正好是两个字节, ⽽且FF⽐FE⼤1.// Big Endian(FEFF) Little Endian(FFFE)NOTE:如果⼀个⽂本⽂件的头两个字节是FE FF, 就表⽰该⽂件采⽤⼤头⽅式; 如果头两个字节是FF FE, 就表⽰该⽂件采⽤⼩头⽅式.5. Unicode与UTF-8之间的转换从表1我们很明显可以得知Unicode与UTF-8的关系, 下⾯以C语⾔实现两者之间的转换.1) 将⼀个字符的Unicode(UCS-2和UCS-4)编码转换成UTF-8编码.// #c---/****************************************************************************** 将⼀个字符的Unicode(UCS-2和UCS-4)编码转换成UTF-8编码.** 参数:* unic 字符的Unicode编码值* pOutput 指向输出的⽤于存储UTF8编码值的缓冲区的指针* outsize pOutput缓冲的⼤⼩** 返回值:* 返回转换后的字符的UTF8编码所占的字节数, 如果出错则返回 0 .** 注意:* 1. UTF8没有字节序问题, 但是Unicode有字节序要求;* 字节序分为⼤端(Big Endian)和⼩端(Little Endian)两种;* 在Intel处理器中采⽤⼩端法表⽰, 在此采⽤⼩端法表⽰. (低地址存低位)* 2. 请保证 pOutput 缓冲区有最少有 6 字节的空间⼤⼩!****************************************************************************/int enc_unicode_to_utf8_one(unsigned long unic, unsigned char *pOutput,int outSize){assert(pOutput != NULL);assert(outSize >= 6);if ( unic <= 0x0000007F ){// * U-00000000 - U-0000007F: 0xxxxxxx*pOutput = (unic & 0x7F);return1;}else if ( unic >= 0x00000080 && unic <= 0x000007FF ){// * U-00000080 - U-000007FF: 110xxxxx 10xxxxxx*(pOutput+1) = (unic & 0x3F) | 0x80;*pOutput = ((unic >> 6) & 0x1F) | 0xC0;return2;}else if ( unic >= 0x00000800 && unic <= 0x0000FFFF ){// * U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx*(pOutput+2) = (unic & 0x3F) | 0x80;*(pOutput+1) = ((unic >> 6) & 0x3F) | 0x80;*pOutput = ((unic >> 12) & 0x0F) | 0xE0;return3;}else if ( unic >= 0x00010000 && unic <= 0x001FFFFF ){// * U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx*(pOutput+3) = (unic & 0x3F) | 0x80;*(pOutput+2) = ((unic >> 6) & 0x3F) | 0x80;*(pOutput+1) = ((unic >> 12) & 0x3F) | 0x80;*pOutput = ((unic >> 18) & 0x07) | 0xF0;return4;}else if ( unic >= 0x00200000 && unic <= 0x03FFFFFF ){// * U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx*(pOutput+4) = (unic & 0x3F) | 0x80;*(pOutput+3) = ((unic >> 6) & 0x3F) | 0x80;*(pOutput+2) = ((unic >> 12) & 0x3F) | 0x80;*(pOutput+1) = ((unic >> 18) & 0x3F) | 0x80;*pOutput = ((unic >> 24) & 0x03) | 0xF8;return5;}else if ( unic >= 0x04000000 && unic <= 0x7FFFFFFF ){// * U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx *(pOutput+5) = (unic & 0x3F) | 0x80;*(pOutput+4) = ((unic >> 6) & 0x3F) | 0x80;*(pOutput+3) = ((unic >> 12) & 0x3F) | 0x80;*(pOutput+2) = ((unic >> 18) & 0x3F) | 0x80;*(pOutput+1) = ((unic >> 24) & 0x3F) | 0x80;*pOutput = ((unic >> 30) & 0x01) | 0xFC;return6;}return0;}// #c---end2) 将⼀个字符的UTF8编码转换成Unicode(UCS-2和UCS-4)编码.<span xmlns="/1999/xhtml" style="">// #c---/****************************************************************************** 将⼀个字符的UTF8编码转换成Unicode(UCS-2和UCS-4)编码.** 参数:* pInput 指向输⼊缓冲区, 以UTF-8编码* Unic 指向输出缓冲区, 其保存的数据即是Unicode编码值,* 类型为unsigned long .** 返回值:* 成功则返回该字符的UTF8编码所占⽤的字节数; 失败则返回0.** 注意:* 1. UTF8没有字节序问题, 但是Unicode有字节序要求;* 字节序分为⼤端(Big Endian)和⼩端(Little Endian)两种;* 在Intel处理器中采⽤⼩端法表⽰, 在此采⽤⼩端法表⽰. (低地址存低位)****************************************************************************/int enc_utf8_to_unicode_one(const unsigned char* pInput, unsigned long *Unic){assert(pInput != NULL && Unic != NULL);// b1 表⽰UTF-8编码的pInput中的⾼字节, b2 表⽰次⾼字节, ...char b1, b2, b3, b4, b5, b6;*Unic = 0x0; // 把 *Unic 初始化为全零int utfbytes = enc_get_utf8_size(*pInput);unsigned char *pOutput = (unsigned char *) Unic;switch ( utfbytes ){case0:*pOutput = *pInput;utfbytes += 1;break;case2:b1 = *pInput;b2 = *(pInput + 1);if ( (b2 & 0xE0) != 0x80 )return0;*pOutput = (b1 << 6) + (b2 & 0x3F);*(pOutput+1) = (b1 >> 2) & 0x07;break;case3:b1 = *pInput;b2 = *(pInput + 1);b3 = *(pInput + 2);if ( ((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80) )return0;*pOutput = (b2 << 6) + (b3 & 0x3F);*(pOutput+1) = (b1 << 4) + ((b2 >> 2) & 0x0F);break;case4:b1 = *pInput;b2 = *(pInput + 1);b3 = *(pInput + 2);b4 = *(pInput + 3);if ( ((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80)|| ((b4 & 0xC0) != 0x80) )return0;*pOutput = (b3 << 6) + (b4 & 0x3F);*(pOutput+1) = (b2 << 4) + ((b3 >> 2) & 0x0F);*(pOutput+2) = ((b1 << 2) & 0x1C) + ((b2 >> 4) & 0x03);break;case5:b1 = *pInput;b2 = *(pInput + 1);b3 = *(pInput + 2);b4 = *(pInput + 3);b5 = *(pInput + 4);if ( ((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80)|| ((b4 & 0xC0) != 0x80) || ((b5 & 0xC0) != 0x80) ) return0;*pOutput = (b4 << 6) + (b5 & 0x3F);*(pOutput+1) = (b3 << 4) + ((b4 >> 2) & 0x0F);*(pOutput+2) = (b2 << 2) + ((b3 >> 4) & 0x03);*(pOutput+3) = (b1 << 6);break;case6:b1 = *pInput;b2 = *(pInput + 1);b3 = *(pInput + 2);b4 = *(pInput + 3);b5 = *(pInput + 4);b6 = *(pInput + 5);if ( ((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80)|| ((b4 & 0xC0) != 0x80) || ((b5 & 0xC0) != 0x80) || ((b6 & 0xC0) != 0x80) )return0;*pOutput = (b5 << 6) + (b6 & 0x3F);*(pOutput+1) = (b5 << 4) + ((b6 >> 2) & 0x0F);*(pOutput+2) = (b3 << 2) + ((b4 >> 4) & 0x03);*(pOutput+3) = ((b1 << 6) & 0x40) + (b2 & 0x3F);break;default:return0;break;}return utfbytes;}// #c---end</span>。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
[字符集]Unicode和UTF-8之间的转换详解
最近在用VC++开发一个小工具,平时用惯了.NET,用起VC++最郁闷的就是字符串处理。
当然最最让人难于琢磨的就是字符集,编码之间的转换。
通过这几天的研究,终于明白了Unicode和UTF-8之间编码的区别。
Unicode是一个字符集,而UTF-8是Unicode的其中一种,Unicode是定长的都为双字节,而UTF-8是可变的,对于汉字来说Unicode占有的字节比UTF-8占用的字节少1个字节。
Unicode为双字节,而UTF-8中汉字占三个字节。
UTF-8编码字符理论上可以最多到6个字节长,然而16位BMP(Basic Multilingual Plane)字符最多只用到3字节长。
下面看一下UTF-8编码表:
U-00000000 - U-0000007F: 0xxxxxxx
U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
10xxxxxx
xxx 的位置由字符编码数的二进制表示的位填入,越靠右的x 具有越少的特殊意义,只用最短的那个足够表达一个字符编码数的多字节串。
注意在多字节串中, 第一个字节的开头"1"的数目就是整个串中字节的数目。
而第一行中以0开头,是为了兼容ASCII编码,为一个字节,第二行就为双字节字符串,第三行为3字节,如汉字就属于这种,以此类推。
(个人认为:其实我们可以简单的把前面的1的个数看成字节数)
为了要将Unicode转换为UTF-8,当然要知道他们的区别到底在什么地方。
下面来看一下,在Unicode中的编码是怎样转换成UTF-8的,在UTF-8中,如果一个字符的字节小于0x80(128)则为ASCII字符,占一个字节,可以不用转换,因为UTF-8兼容ASCII编码。
假如在Unicode中汉字“你”的编码为“u4F60”,把它转换为二进制为100111101100000,然后按照UTF-8的方法进行转换。
可以将Unicode二进制从地位往高位取出二进制数字,每次取6位,如上述的二进制就可以分别取出为如下所示的格式,前面按格式填补,不足8位用0填补。
unicode: 100111101100000 4F60
utf-8:11100100,10111101,10100000 E4BDA0
从上面就可以很直观的看出Unicode到UTF-8之间的转换,当然知道了UTF-8的格式后,就可以进行逆运算,就是按照格式把它在二进制中的相应位置上取出,然后在转换就是所得到的Unicode字符了(这个运算可以通过“位移”来完成)。
如上述的“你”的转换,由于其值大于0x800小于0x10000,因此可以判断为三字节存储,则最高位需要向右移“12”位再根据三字节格式的最高位为11100000(0xE0)求或(|)就可以得到最高位的值了。
同理第二位则是右移“6”位,则还剩下最高位和第二位的二进制值,可以通过与111111(0x3F)求按位于(&)操作,再和11000000(0x80)求或(|)。
第三位就不用移位了,只要直接取最后六位(与111111(ox3F)取&),在与11000000(0x80)求或(|)。
OK了,转换成功!在VC++中的代码如下所示(Unicode到UTF-8的转换)。
1const wchar_t pUnicode = L"你";
2char utf8[3+1];
3memset(utf8,0,4);
4utf8[0] = 0xE0|(pUnicode>>12);
5utf8[1] = 0x80|((pUnicode>>6)&0x3F);
6utf8[2] = 0x80|(pUnicode&0x3F);
7utf8[3] = "\0";
8//char[4]就是UTF-8的字符“你”了。
当然在UTF-8到Unicode的转换也是通过移位等来完成的,就是把UTF-8那些格式相应的位置的二进制数给揪出来。
在上述例子中“你”为三个字节,因此要每个字节进行处理,有高位到低位进行处理。
在UTF-8中“你”为11100100,10111101,10100000。
从高位起即第一个字节11100100就是把其中的"0100"给取出来,这个很简单只要和11111(0x1F)取与(&),由三字节可以得知最到位肯定位于12位之前,因为每次取六位。
所以还要将得到的结果左移12位,最高位也就这样完成了0100,000000,000000。
而第二位则是要把“111101”给取出来,则只需将第二字节10111101和111111(0x3F)取与(&)。
在将所得到的结果左移6位与最高字节所得的结果取或(|),第二位就
这样完成了,得到的结果为0100,111101,000000。
以此类推最后一位直接与111111(0x3F)取与(&),再与前面所得的结果取或(|)即可得到结果0100,111101,100000。
OK,转换成功!在VC++中的代码如下所示(UTF-8到Unicode的转换)。
1//UTF-8格式的字符串
2const char* utf8 = "你";
3wchar_t unicode;
4unicode = (utf8[0] & 0x1F) << 12;
5unicode |= (utf8[1] & 0x3F) << 6;
6unicode |= (utf8[2] & 0x3F);
7//unicode is ok!
当然在编程过程中不可能只转换一个字符,这里需要注意的是字符的长度一定要算清楚,不然会带来...以上就是我这几天研究的结果,至于Unicode的转换为GB2312在MFC中Windows有自带的API(WideCharToMultiByte)可以转换。
这样也就能够将UTF-8格式转换为GB2312了,这里就不再赘述,如果大家有更好的方法希望指教。