微光互联 TX800-U 扫码器无法输出中文到光标的问题( 三 )

谜之编码风格,另外这接口设计的也有点凌乱,程序中出现了好多魔数:1017/1018/2041/200/7,看着头大 。所幸读取的数据位于 readBuffers 缓冲中,只要对它做个编码转换就 OK 啦 。
编码转换windows 中文版编码一般是 gb2312,汉字源编码则可能是 utf-8,为了验证这一点,搬出来了 iconv:
$ echo "浜琈D0926" | iconv -f 'utf-8' -t 'cp936'京MD0926看来确实如此,注意这里使用 cp936 而不是  gb2312 作为 iconv 的第二个参数 。如果没有 iconv,也有许多线上的编码转换工具可用:

微光互联 TX800-U 扫码器无法输出中文到光标的问题

文章插图
确定了字符集转换方向,直接从网上搜罗来一些现成的实现:
std::wstring utf8_to_unicode(std::string const& utf8){    int need = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, NULL, 0);    if (need > 0)    {        std::wstring unicode;        unicode.resize(need);        MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, &unicode[0], need);        return unicode;    }    return std::wstring();}std::string unicode_to_gb2312(std::wstring const& unicode){    int need = WideCharToMultiByte(936, 0, unicode.c_str(), -1, NULL, 0, NULL, NULL);    if (need > 0)    {        std::string gb2312;        gb2312.resize(need);        WideCharToMultiByte(936, 0, unicode.c_str(), -1, &gb2312[0], need, 0, 0);        return gb2312;    }    return std::string();}std::string utf8_to_gb2312(std::string const& utf8){    std::wstring unicode = utf8_to_unicode(utf8);    return unicode_to_gb2312(unicode);}windows 上编码转换都是先转到 unicode,再转其它编码,比较好理解 。那么 demo 中的输出就可以改为:
std::string gb2312 = utf8_to_gb2312(std::string((char *)readBuffers, datalen));printf("%.*s\n", gb2312.lenght(), gb2312.c_str());再次运行:
二维码长度:10京MD0926恢复正常!
输出到剪贴板上面的过程虽然能正确解析 utf-8 数据了,但还需要用户复制 console 输出的结果,很不方便,如果能将结果直接输出到剪贴板上岂不是很爽?说干就干:
void copy_to_system_clipboard(std::string const& data){    printf("ready to copy data: %s\n", data.c_str());    BOOL ret = OpenClipboard(NULL);    if (!ret)    {        printf("open clipboard failed\n");        return;    }    do    {        ret = EmptyClipboard();        if (!ret)        {            printf("empty clipboard failed\n");            break;        }        HGLOBAL hdata = GlobalAlloc(GMEM_MOVEABLE, data.length() + 1);        if (hdata == NULL)        {            printf("alloc data for clipboard failed");            break;        }        char* str = (char *) GlobalLock(hdata);        memcpy(str, data.c_str(), data.length());        str[data.length()] = 0;        GlobalUnlock(hdata);         // HANDLE h = SetClipboardData(CF_UNICODETEXT, hdata);        HANDLE h = SetClipboardData(CF_TEXT, hdata);        if (!h)        {            printf("set clipboard data failed");            break;        }        printf("copy to clipboard ok\n");    } while (0);    CloseClipboard();}

经验总结扩展阅读