美文网首页
utf-8编码转gbk(C语言实现, 解决控制台输出utf-8乱

utf-8编码转gbk(C语言实现, 解决控制台输出utf-8乱

作者: zzkdev | 来源:发表于2018-02-06 21:17 被阅读0次

    今天在windows控制台上打印utf-8字符时出现了乱码,然后就折腾了一下发现在简体中文版上的windows默认的代码页是936(gbk编码),在控制台上输入chcp 65001解决之(65001是UTF-8代码页编号),但是我这么爱钻研(瞎折腾)怎么可能就这么完事了呢,就尝试了下用C语言实现utf-8转化成gbk编码(还顺便学习了下几种编码),下面是解决方法。

    嗯。。还有我学习时看的一个资料,介绍编码知识的

    http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

    解决方法

    1.使用代码更改活动代码页

    system("chcp 65001");

    也可以使用windows的一个API(设置输出代码页),效果一样

    SetConsoleOutputCP(65001);

    还有另外一个API是SetConsoleCP(),这个API设置的是输入代码页,在输出时并不起作用

    C语言标准里面还提供了一个函数来设置代码页Setlocale(),不过没有测试过

    2.将utf-8转换成gbk编码

    原理是利用windows的两个API,将UTF-8转成unicode编码,再转成gbk编码

    下面是对两个函数的介绍

    函数原型

    int MultiByteToWideChar(

    UINT CodePage,

    DWORD dwFlags,

    LPCSTR lpMultiByteStr,

    int cchMultiByte,

    LPWSTR lpWideCharStr,

    int cchWideChar);

    函数功能 

    该函数映射一个字符串到一个宽字符(unicode)的字符串。由该函数映射的字符串没必要是多字节字符组。

    参数

    CodePage:指定执行转换的代码页,这个参数可以为系统已安装或有效的任何代码页所给定的值。我们用到的是下面两个值(当然你也可以指定别的值):

    CP_ACP:ANSI代码页(简体中文Windows操作系统中,ANSI 编码代表 GBK 编码)

    CP_UTF8:使用UTF-8转换

    dwFlags: 指定如何处理没有转换的字符,但不设此参数函数会运行的更快一些,我都是把它设为0。 可设的值如下表所示:

    WC_NO_BEST_FIT_CHARS

    把不能直接转换成相应多字节字符的Unicode字符转换成lpDefaultChar指定的默认字符。也就是说,如果把Unicode转换成多字节字符,然后再转换回来,你并不一定得到相同的Unicode字符,因为这期间可能使用了默认字符。此选项可以单独使用,也可以和其他选项一起使用。

    WC_COMPOSITECHECK

    把合成字符转换成预制的字符。它可以与后三个选项中的任何一个组合使用,如果没有与他们中的任何一个组合,则与选项WC_SEPCHARS相同。

    WC_ERR_INVALID_CHARS

    此选项会致使函数遇到无效字符时失败返回,并且GetLastError会返回错误码ERROR_NO_UNICODE_TRANSLATION。否则函数会自动丢弃非法字符。此选项只能用于UTF8。

    WC_DISCARDNS   

    转换时丢弃不占空间的字符,与WC_COMPOSITECHECK 一起使用

    WC_SEPCHARS

    转换时产生单独的字符,此是默认转换选项,WC_COMPOSITECHECK一起使用

    WC_DEFAULTCHAR

    转换时使用默认字符代替例外的字符,(最常见的如’?’),与WC_COMPOSITECHECK一起使用。

    对于下列代码页,dwFlags必须为0,否则函数返回错误码ERROR_INVALID_FLAGS。 50220 50221 50222 50225 50227 50229 52936 54936 57002到57011 65000(UTF7) 42(Symbol)

    对于UTF8,dwFlags必须为0或WC_ERR_INVALID_CHARS,否则函数都将失败返回并设置错误码ERROR_INVALID_FLAGS,你可以调用GetLastError获得。

    lpMultiByteStr:指向将被转换字符串的字符。

    cchMultiByte:指定由参数lpMultiByteStr指向的字符串中字节的个数。如果这个值为-1,字符串将被设定为以NULL为结束符的字符串,并且自动计算长度。

    lpWideCharStr:指向接收被转换字符串的缓冲区。

    cchWideChar:指定由参数lpWideCharStr指向的缓冲区的字节个数。若此值为零,函数返回缓冲区所必需的宽字符数,在这种情况下,lpWideCharStr中的缓冲区不被使用。

    返回值:如果函数运行成功,并且cchWideChar不为零,返回值是由lpWideCharStr指向的缓冲区中写入的宽字符数;如果函数运行成功,并且cchMultiByte为零,返回值是接收到待转换字符串的缓冲区所需求的宽字符数大小。如果函数运行失败,返回值为零。

    函数原型

    int WideCharToMultiByte(

    UINT CodePage,

    DWORD dwFlags,

    LPCWSTR lpWideCharStr,

    int cchWideChar,

    LPSTR lpMultiByteStr,

    int cbMultiByte,

    LPCSTR lpDefaultChar,

    LPBOOL lpUsedDefaultChar);

    函数功能 

    此函数把宽字符串转换成指定的新的字符串,如ANSI,UTF8等,新字符串不必是多字节字符集。 

    参数

    lpWideCharStr : 待转换的宽字符串。

    cchWideChar : 待转换宽字符串的长度,-1表示转换到字符串结尾。

    lpMultiByteStr : 接收转换后输出新串的缓冲区。

    cbMultiByte :输出缓冲区大小,如果为0,lpMultiByteStr将被忽略,函数将返回所需缓冲区大小而不使用lpMultiByteStr。

    lpDefaultChar : 指向字符的指针, 在指定编码里找不到相应字符时使用此字符作为默认字符代替。如果为NULL则使用系统默认字符。对于要求此参数为NULL的dwFlags而使用此参数,函数将失败返回并设置错误码ERROR_INVALID_PARAMETER。

    lpUsedDefaultChar :开关变量的指针,用以表明是否使用过默认字符。对于要求此参数为NULL的dwFlags而使用此参数,函数将失败返回并设置错误码ERROR_INVALID_PARAMETER。lpDefaultChar和lpUsedDefaultChar都设为NULL,函数会更快一些。

    返回值 :如果函数成功,且cbMultiByte非0,返回写入lpMultiByteStr的字节数(包括字符串结尾的null);cbMultiByte为0,则返回转换所需字节数。函数失败,返回0。


    下面是简单的函数实现

    void utf8ToGbk(char *utf8String, char *gbkString)

    {

    wchar_t *unicodeStr = NULL;

    int nRetLen = 0;

    nRetLen = MultiByteToWideChar(CP_UTF8, 0, utf8String, -1, NULL, 0);

    //求需求的宽字符数大小

    unicodeStr = (wchar_t *)malloc(nRetLen * sizeof(wchar_t));

    nRetLen = MultiByteToWideChar(CP_UTF8, 0, utf8String, -1, unicodeStr, nRetLen);

    //将utf-8编码转换成unicode编码

    nRetLen = WideCharToMultiByte(CP_ACP, 0, unicodeStr, -1, NULL, 0, NULL, 0);

    //求转换所需字节数

    nRetLen = WideCharToMultiByte(CP_ACP, 0, unicodeStr, -1, gbkString, nRetLen, NULL, 0);

    //unicode编码转换成gbk编码

    free(unicodeStr);

    }


    第三篇文章哈哈哈哈


    人生是一场规模庞大的摸彩游戏,只有中奖的彩票展现在我们眼前。——《纸牌的秘密》


    给我点十个赞我就买杯可乐庆祝下

    相关文章

      网友评论

          本文标题:utf-8编码转gbk(C语言实现, 解决控制台输出utf-8乱

          本文链接:https://www.haomeiwen.com/subject/gkzgzxtx.html