• 编码问题学习【2】


    多字节和宽字符

    C++中string / char* ,wstring / wchar_t*

    C++測试

    window以下

    char* cName = "北京市";
    // 多字节转化成宽字符字符串!
    unsigned short wsName[50] = {0};
    int wideCharCount = MultiByteToWideChar(CP_ACP, 0, (LPSTR)cName, -1, NULL, 0) - 1;
    MultiByteToWideChar(CP_ACP, 0, (LPSTR)cName, -1, (LPWSTR)wsName, wideCharCount + 1);
    
    for (int i=0; i<wideCharCount; i++)
    {
    	printf("%d ", wsName[i]);
    }printf("
    ");
    输出
    21271 20140 24066

    Linux以下

    測试代码例如以下:
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    #include <locale.h>
    #include <iostream>
    #include <string>
    using namespace std;
    
    void multibyte_to_widechar_test();
    void read_file(const char* fname);
    void dump_uchar(unsigned char ch);
    
    int main()
    {
        multibyte_to_widechar_test();
        read_file("chs");
    
        printf("any key pressed to exit...
    ");
        getchar();
        
        return 0;
    }
    
    void multibyte_to_widechar_test()
    {
        typedef string str_t;
        str_t cur_loc = setlocale(LC_ALL, NULL);
        printf("cur_locale = %s
    ", cur_loc.c_str());   
        setlocale(LC_ALL, "zh_CN.GBK"); 
        
        char mb_buf[100];
        strcpy(mb_buf, "北京市");
        int mbstr_len = strlen(mb_buf);
        
        wchar_t* wcstr = NULL; 
        int wcstr_len = mbstowcs(wcstr, mb_buf, 0) + 1; 
    
        printf("mb_len = %d, wc_len = %d
    ", mbstr_len, wcstr_len);
    
        wcstr = new wchar_t[wcstr_len];
        int ret = mbstowcs(wcstr, mb_buf, mbstr_len);
    
        if (ret <= 0)
        {
            printf("转化失败
    ");
        }
        else    
        {
            printf("转化成功
    ");
            // wsprintf(L"%ls
    ", wcstr);
    
            printf("view1 =====
    ");
            
            for (int i=0; i<wcstr_len - 1; i++) 
            {       
                int code = (int)wcstr[i];
                printf("%d	", code);
            } printf("
    ");
            
            printf("view2 =====
    ");
            for (int i=0; i<wcstr_len - 1; i++) 
            {       
                int code = (int)wcstr[i];
                dump_uchar( (unsigned char)(code/256) );
                dump_uchar( (unsigned char)(code%256) );
            } printf("
    ");
            
        }
    
        setlocale(LC_ALL, cur_loc.c_str());
    
    }
    
    void dump_uchar(unsigned char ch)
    {
        const char* str = "0123456789abcdef";
    
        printf("0x%c%c	", str[ch/16], str[ch%16]);
    }
    
    void read_file(const char* fname)
    {
        FILE* fp = fopen(fname, "r");
    
        if (!fp)
        {
            return;
        }
    
        printf("===============
    ");
    
        char buffer[100] = {0};
        fgets(buffer, 100, fp);
        printf("%s", buffer);
    
        printf("view1 =========== 
    ");
        int len = strlen(buffer) - 1;
        for (int i=0; i<len; i++)
        {
            dump_uchar((unsigned char)buffer[i]);
        }printf("
    ");
    
        printf("view2 =========== 
    ");
        for (int i=0; i<len; i+=2)
        {
            unsigned char down = (unsigned char)buffer[i];
            unsigned char high = (unsigned char)buffer[i+1];
            printf("%d ", (high<<8)|down);
        } printf("
    ");
    
        fclose(fp);
    }
    multibyte_to_widechar_test函数将多字节编码转化成unicode编码。然后输出unicode串内容。
    read_file尝试读取文件里字符串编码内容。

    chs通过vi直接生成,内容为”北京市“,,/base_profile中设置例如以下:
    export LC_ALL="zh_CN.GBK"
    所以chs文件的编码默认是gbk。

    g++ test.cpp -o app_test,然后执行输出:
    root@h10-xx-xx-xx:~/peteryfren/cpp/encode_app> ./app_test 
    cur_locale = C
    mb_len = 6, wc_len = 4
    转化成功
    view1 =====
    21271   20140   24066
    view2 =====
    0x53    0x17    0x4e    0xac    0x5e    0x02
    ===============
    北京市
    view1 =========== 
    0xb1    0xb1    0xbe    0xa9    0xca    0xd0
    view2 =========== 
    45489 43454 53450 
    any key pressed to exit...
    “北京市”的unicode编码值与window上输出一致。“北京市”的gbk2312编码为45489,43454,53450。
    同一时候linux vi创建的文件编码为gbk,与base_profile中设置一致。

    BTW linux下通过iconv将utf-8编码文件转化成unicode:
    iconv -f UTF-8 -t GBK test.txt -o pp.txt

    python2.7測试

    >>> s = u'北京市'
    >>> s
    u'u5317u4eacu5e02'
    >>> gbks = '北京市'
    >>> gbks
    'xb1xb1xbexa9xcaxd0'
    >>> s.encode('utf-8')
    'xe5x8cx97xe4xbaxacxe5xb8x82'
    2.7以下加u表示unicode编码,不加u使用了gbk编码。
    python3.3以下不能输出字符串的字节码,
    >>s
    等价于,
    >>print(s)

    windows文本编码验证

    1. ANSI
    使用windows自带的记事本创建一个默认的txt,叫npd.txt
    用UE打开,16进制视图下:

    此时文件里中文编码为gbk2312编码。与Linux上文件编码输出一致。

    2. unicode
    记事本打开npd.txt,然后另存为,此时能够看到编码是ANSI,选择unicode,另存为npd_u.txt

    unicode编码,内容与上文中windows、linux上输出一致。

    3,utf-8
    相同打开npd.txt,另存为,编码选择utf-8,另存为npd_utf8.txt

    utf-8输出与python中实验一致,这个是肯定的。

    gb18030和通常的gdk都是对gb2312的扩展,全部已经包括在gb2312中的汉字编码保持不变。

    參考

    1. http://blog.csdn.net/xiaobai1593/article/details/7063535

    2. GBK2312编码表參见:http://ff.163.com/newflyff/gbk-list/

    3. unicode编码表參见:http://jlqzs.blog.163.com/blog/static/2125298320070101826277/


  • 相关阅读:
    从0开始学习C#第三天
    金盾视频加密器V2014视频加密原理分析
    从0开始学习C#第二天
    从0开始学习C#第一天
    hook NtTerminateProcess进行应用的保护
    Wireshark简单使用教程3——附视频
    Wireshark简单使用教程2——附视频
    Wireshark简单使用教程1——附视频
    一个bat病毒分析(part1)
    社团的CTF逆向题WriteUp
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4489698.html
Copyright © 2020-2023  润新知