• 字符集研究之不同字符集的转换方式


    作者:朱金灿

    来源:http://blog.csdn.net/clever101

     

            在上篇文章中介绍了多字节字符集和unicode字符集,今天介绍下两大字符集之间的转换方式。

     

           首先谈谈的是微软对于unicode字符集的态度。在windows的开发体系下。unicode字符字符集被称为宽字节字符集,多字节字符集被称为窄字符集。微软对unicode字符集是大力支持的。从下面几点能够看出:从windows2000開始使用unicode进行开发;Windows CE 本身就是使用Unicode的一种操作系统,全然不支持ANSI版Windows API函数。新建的VCproject默认使用的是unicode字符集(utf16)。那么问题来了,作为一个C++程序猿,是否该使用unicode字符集。

     

           为什么使用Unicode字符集?

    提升执行效率。比方Windows内核本身是基于unicode字符的,非unicode字符传进入要先转成unicode字符(《windows核心编程有详解》)。在不同语言中能够方便交换数据,比方在英文版操作系统中输入中文路径。假设是非unicode字符同一时候又没有安装中文字符集,那么就会出现乱码。

     

             为什么不使用Unicode字符集?由于传统的势力非常强大,非常多跨平台的第三方库都是基于多字节字节集进行开发,还有就是编程习惯,比方在Windows下开发,大家耳熟能详的是计算字符串长度的函数是strlen。谁会去用宽字节版的wcslen呢。

    详见我曾经写的文章:

    unicode字符集。用还是不用?

     

           最后谈谈多字节字符集和unicode字符集。

    两种方式。一种是使用跨平台的iconv库,演示样例代码例如以下:

    include <stdio.h>
    #include <stdlib.h>
    #include <string>
    using namespace std;
    
    #include <iconv.h> //编码转换库
    
    #define OUTLEN 255 //文件路径长度
    
    //代码转换:从一种编码转为还有一种编码
    int code_convert(char *from_charset, char *to_charset, char *inbuf, size_t inlen, char *outbuf, size_t  outlen)
    {
    iconv_t cd;
    char **pin = &inbuf;
    char **pout = &outbuf;
    
    cd = iconv_open(to_charset,from_charset);
    if (cd==0) 
    return -1;
    memset(outbuf,0,outlen);
    
    if (iconv(cd,pin,&inlen,pout,&outlen)==-1)
    return -1;
    iconv_close(cd);
    return 0;
    }
    //UNICODE码转为GB2312码
    int u2g(char *inbuf, size_t  inlen, char *outbuf, size_t  outlen)
    {
    return code_convert("utf-8","gb2312",inbuf,inlen,outbuf,outlen);
    }
    //GB2312码转为UNICODE码
    int g2u(char *inbuf, size_t inlen, char *outbuf, size_t outlen)
    {
    return code_convert("gb2312","utf-8",inbuf,inlen,outbuf,outlen);
    }
    
    //执行SQL语句回调函数
    static int _sql_callback(void* pUsed, int argc, char** argv, char** ppszColName)
    {
    for(int i=0; i<argc; i++)
    {
    printf("%s = %s/n", ppszColName[i], argv[i]==0 ? "NULL" : argv[i]);
    }
    return 0;
    }
    
    void main()
    {
    char *in_gb2312 = "D://控制点库//GCPDB.3sdb";
    
    char out[OUTLEN];
      
    //gb2312码转为unicode码
    g2u(in_gb2312,strlen(in_gb2312),out,OUTLEN);
    printf("gb2312-->unicode out=%s /n",out);
    }

    还有一种方式是使用使用WindiwsAPI,演示样例代码例如以下:

    std::string MbcsToUtf8( const char* pszMbcs )  
        {  
            std::string str;  
            WCHAR   *pwchar=0;  
            CHAR    *pchar=0;  
            int len=0;  
            int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;  
            len=MultiByteToWideChar(codepage, 0, pszMbcs, -1, NULL,0);  
            pwchar=new WCHAR[len];  
            if(pwchar!=0)  
            {  
                len = MultiByteToWideChar(codepage, 0, pszMbcs, -1, pwchar, len);  
                if( len!=0 )  
                {  
                    len = WideCharToMultiByte(CP_UTF8, 0, pwchar, -1, 0, 0, 0, 0);  
                    pchar=new CHAR[len];  
                    if(pchar!=0)  
                    {  
                        len = WideCharToMultiByte(CP_UTF8, 0, pwchar, -1, pchar, len,0, 0);  
                        if(len!=0)                  
                        {  
                            str = pchar;                     
                        }  
                        delete pchar;  
                    }  
                    delete pwchar;  
                }  
            }  
            return str;  
    }  

    參考文献:

    1. 使用SQLite3支持中文路径

  • 相关阅读:
    [MFC美化] Skin++使用详解-使用方法及注意事项
    [MFC美化] SkinMagic使用详解3- 常见使用问题解答
    [MFC美化] SkinMagic使用详解2- SkinMagic常用函数介绍
    [MFC美化] SkinMagic使用详解1- SkinMagic使用流程
    MFC 自定义控件
    error C3872: “0x3000”: 此字符不允许在标识符中使用
    websocket学习
    Servlet学习1
    Git使用学习
    异常捕获测试
  • 原文地址:https://www.cnblogs.com/wgwyanfs/p/7400497.html
Copyright © 2020-2023  润新知