新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论高级C/C++编程、代码重构(Refactoring)、极限编程(XP)、泛型编程等话题
    [返回] 计算机科学论坛计算机技术与应用『 C/C++编程思想 』 → MFC下Unicode到UTF-8格式的转换 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 5344 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: MFC下Unicode到UTF-8格式的转换 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客楼主
    发贴心情 MFC下Unicode到UTF-8格式的转换

    ●MFC一般编程习惯到 UNICODE宽字节字符集编程
    UNICODE 通过用双字节来表示一个字符,从而在更大范围内将数字代码映射到多种语言的字符集。


    MFC 以宏的形式提供了将一般文本转换成 UNICODE 数据类型的途径。
    开发人员只需要稍微改变一下编写代码的习惯便可以轻松编写支持 UNICODE 的应用。

    定义部分:
    通用 多字节 宽字节
    _TCHAR/TCHAR char wchar_t
    _T 或_TEXT char 常量字符串 wchar_t 常量字符串 L
    LPTSTR char *(或win32下LPSTR) wchar_t *
    LPCTSTR const char * LPCSTR const wchar_t *


    通用形式就是自动的判断当前是否定义了_UNICODE字符集,

    例 如果是的话

    typedef wchar_t TCHAR;

    不是的话
    typedef char TCHAR;


    例:
    MFC中CString 类也通过一种通用定义形式

    通用形式下
    typedef ATL::CStringT< TCHAR, StrTraitMFC< TCHAR > > CString;
    宽字节字符集
    typedef ATL::CStringT< wchar_t, StrTraitMFC< wchar_t > > CStringW;
    ANSI节字符集
    typedef ATL::CStringT< char, StrTraitMFC< char > > CStringA;


    操作系统对UNICODE的支持
    Win98 只支持ANSI
    win2000 支持ANSI 支持UNICODE
    wince 只支持UNICODE


    ●UNICODE 转换到 UTF-8
    UTF-8 编码字符理论上可以最多到 6 个字节长
    注意在多字节串中, 第一个字节的开头"1"的数目就是整个串中字节的数目.


    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


    我使用的函数:

    /*-------------------------------------------------------------------------------------
    wchar_t (UNICODE 2bit)->char (UTF-8)(multi bit )
    它通过简单的码位析取与分配即可完成.

    本函数提供这一实现.
    dest_str:
    宽字节字符转换为UTF-8编码字符的目标地址.
    src_wchar:被转换的宽字节源字符.
    返回值:
    返回实际转换后的字符的字节数. 若遇到错误或检测到非法字节序列, 则返回-1.

    注意! 传递进来的宽字符应是能被合法转换为UTF-8编码的字符.
    --------------------------------------------------------------------------------------
    */

    size_t 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’; // 用于宽字符位置析取和位移(右移6位)
    unsigned char tmp_char = ’0’;

    if (!src_wchar)//
    return (size_t)-1;

    for (;;) // 检测字节序列长度
    {
    if (src_wchar <= 0x7f){ // <=01111111
    count_bytes = 1; // ASCII字符: 0xxxxxxx( ~ 01111111)
    byte_one = 0x7f; // 用于位与运算, 提取有效位值, 下同
    utf_one = 0x0;
    break;
    }
    if ( (src_wchar > 0x7f) && (src_wchar <= 0x7ff) ){ // <=0111,11111111
    count_bytes = 2; // 110xxxxx 10xxxxxx[1](最多11个1位, 简写为11*1)
    byte_one = 0x1f; // 00011111, 下类推(1位的数量递减)
    utf_one = 0xc0; // 11000000
    break;
    }
    if ( (src_wchar > 0x7ff) && (src_wchar <= 0xffff) ){ //0111,11111111<=11111111,11111111
    count_bytes = 3; // 1110xxxx 10xxxxxx[2](MaxBits: 16*1)
    byte_one = 0xf; // 00001111
    utf_one = 0xe0; // 11100000
    break;
    }
    if ( (src_wchar > 0xffff) && (src_wchar <= 0x1fffff) ){ //对UCS-4的支持..
    count_bytes = 4; // 11110xxx 10xxxxxx[3](MaxBits: 21*1)
    byte_one = 0x7; // 00000111
    utf_one = 0xf0; // 11110000
    break;
    }
    if ( (src_wchar > 0x1fffff) && (src_wchar <= 0x3ffffff) ){
    count_bytes = 5; // 111110xx 10xxxxxx[4](MaxBits: 26*1)
    byte_one = 0x3; // 00000011
    utf_one = 0xf8; // 11111000
    break;
    }
    if ( (src_wchar > 0x3ffffff) && (src_wchar <= 0x7fffffff) ){
    count_bytes = 6; // 1111110x 10xxxxxx[5](MaxBits: 31*1)
    byte_one = 0x1; // 00000001
    utf_one = 0xfc; // 11111100
    break;
    }
    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);///后6位与byte_other 00111111
    dest_str[i - 1] = (tmp_char | utf_other);/// 在前面加10----跟10000000或
    tmp_wchar >>= 6;//右移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;
    }
    /*------------------------------------------------------------------------
    * 通过g_f_wctou8函数实现 CString (UNICODE下 ) 到 char *(UTF-8) 的转换
    * wstr 为要转换的UNICODE-16的CString的一个引用
    * *p 为存UTF-8格式的地址
    *
    目前我的做法是:
    * 循环将CString 中的宽字符 利用上面的g_f_wctou8()来转换,并存到char *p中

    * 这里的char *p是 要传给Client SDK,出来的格式就是UTF-8格式的
    *

    *-------------------------------------------------------------------------
    */
    int 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
    {
    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];//第一个值附给p
    j++;
    if(r>1)
    {
    for(size_t x=1;x
    {
    p[j]=c[x];
    j++;
    }
    }
    }
    p[j]=’0’;
    return 1;
    }
    /*-----------------------------------------------------------------------------
    char *-->wchar_t
    它通过简单的码位截取与合成即可完成.
    本函数提供这一实现.
    dest_wchar:
    保存转换后的宽字节字符目标地址.
    src_str:
    被转换的UTF-8编码源字符的多字节序列.
    返回值:
    返回被转换的字符的字节数. 若遇到错误或检测到非法字节序列, 则返回-1.

    注意! 传递进来的宽字符应是能被合法转换为UTF-8编码的字符.
    ------------------------------------------------------------------------------*/
    size_t g_f_u8towc(wchar_t &dest_wchar, const unsigned char * src_str)
    {
    int count_bytes = 0;
    unsigned char byte_one = 0, byte_other = 0x3f; // 用于位与运算以提取位值 0x3f-->00111111
    wchar_t tmp_wchar = L’0’;

    if (!src_str)
    return (size_t)-1;

    for (;;) // 检测字节序列长度,根据第一个字节头的1个个数
    {
    if (src_str[0] <= 0x7f){
    count_bytes = 1; // ASCII字符: 0xxxxxxx( ~ 01111111)
    byte_one = 0x7f; // 用于位与运算, 提取有效位值, 下同 01111111
    break;
    }
    if ( (src_str[0] >= 0xc0) && (src_str[0] <= 0xdf) ){
    count_bytes = 2; // 110xxxxx(110 00000 ~ 110 111111)
    byte_one = 0x1f; //00011111 第一字节有效位的个数
    break;
    }
    if ( (src_str[0] >= 0xe0) && (src_str[0] <= 0xef) ){
    count_bytes = 3; // 1110xxxx(1110 0000 ~ 1110 1111)
    byte_one = 0xf; //00001111
    break;
    }
    if ( (src_str[0] >= 0xf0) && (src_str[0] <= 0xf7) ){
    count_bytes = 4; // 11110xxx(11110 000 ~ 11110 111)
    byte_one = 0x7;
    break;
    }
    if ( (src_str[0] >= 0xf8) && (src_str[0] <= 0xfb) ){
    count_bytes = 5; // 111110xx(111110 00 ~ 111110 11)
    byte_one = 0x3;
    break;
    }
    if ( (src_str[0] >= 0xfc) && (src_str[0] <= 0xfd) ){
    count_bytes = 6; // 1111110x(1111110 0 ~ 1111110 1)
    byte_one = 0x1;
    break;
    }
    return (size_t)-1; // 以上皆不满足则为非法序列
    }
    // 以下几行析取UTF-8编码字符各个字节的有效位值
    //先得到第一个字节的有效位数据
    tmp_wchar = src_str[0] & byte_one;
    for (int i=1; i
    {
    tmp_wchar <<= 6; // 左移6位后与后续字节的有效位值"位或"赋值
    tmp_wchar = tmp_wchar | (src_str[i] & byte_other);//先与后或
    }
    // 位值析取__End!
    dest_wchar = tmp_wchar;
    return count_bytes;
    }
    /*-------------------------------------------------------------------------
    目的 :实现 UTF-8格式 的(char *) p->(UNICODE 下 CString )wstr 的转化
    循环利用g_f_u8towc()这个函数来把char *p转换成宽字符,再存到CString 中!
    ----------------------------------------------------------------------------
    */
    CString g_f_pchar_to_wcs(const unsigned char * p )
    {
    CString wstr(_T(""));
    wchar_t wc=L’1’;
    size_t r=0; //size_t unsigned integer Result of sizeof operator
    while (1)
    {
    if(*p==NULL||*p==’0’)//如果为空或者结束则为跳出循环
    break;
    r=g_f_u8towc(wc,p);//从UTF-8格式的地址中,读一个wchar_t出来
    if(r==-1)//出现错误
    AfxMessageBox(_T("g_f_u8towc error"));
    p=p+r; //移位,准备下一次的转换
    wstr+=wc;//给CString 附值
    }

    return wstr;

    }


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2006/2/7 8:51:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 C/C++编程思想 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/11/26 0:52:16

    本主题贴数1,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    80.078ms