Unicode编码与大端小端

大端小端区别:

举例:

一个4字节的整型数据 0x12345678 高字节是0x12, 低字节是0x78,这个不用多说吧

存储地址假设为0x00000000 0x00000001 0x00000002 0x00000003, 地址逐渐变大,这个不用多说吧

 

那么如果是大端方式存储:

0x00000000 : 0x12

0x00000001 : 0x34

0x00000002 : 0x56

0x00000003 : 0x78

 

如果是小端方式存储:

0x00000000 : 0x78

0x00000001 : 0x56

0x00000002 : 0x34

0x00000003 : 0x12

 

Unicode编码:

Unicode编码:国际标准字符集,它将世界各种语言的每个字符定义一个唯一的编码,以满足跨语言、跨平台的文本信息转换。 --网上找的套话,说一下。

简单说就是英文用一个字节就可以表达所有字符了,而Unicode使用多个字节编码汉字,就是这么意思。

一般使用2个字节,基本常用汉字就包括了。

 

重点来了:

Unicode按照什么字节序编码的?

那就要看我们本机是大端还是小端方式了。

还是举例说明啊:

假如本机是大端方式,而别人给我们的数据也是大端方式排列的,那没有关系,直接使用相应语言的编码函数获取字符串就可以了。

假如本机是大端方式,而别人给我们的数据是小端方式排列的,那就需要一个重新排序,简单点说就是将两个字节颠倒位置就可以了。

顺便贴一下,怎么查看本机是大端还是小端排序,自己写的一个demo:

int _tmain(int argc, _TCHAR* argv[])
{

    printf("Hello World !\n");

    char aa[4] = {0x12,0x34, 0x56, 0x78};
    printf("the index 0 is: %x\n", aa[0]);

    getchar();

    return 0;
}

如果输出:0x12,那么就是大端,输出0x78就是小端。

 

实际情况说明一下:

环境:c#, 获取中文歌名

数据排列方式:小端

本机默认方式:大端

编码方式:采用Unicode

使用的API: Encoding.Unicode.GetString()

问题:出现乱码

原因:

  1. 调试时候查看,发现每次获取到的数据是6个字节,按照2个字节编码一个中文汉字习惯,那么别人给我的是3个汉字。
  2. 别人给我的数据是按照小端方式排列的,也就是说第一个汉字所占的两个字节数据Data[0]表示低字节数据,Data[1]表示高字节数据,然后我就直接传给API Encoding.Unicode.GetString()了,结果发现乱码。

解决措施:

  1. 查询网上资料后发现存在大小端问题,于是查看自己的机器编码方式,发现是大端。
  2. 于是乎自定义函数,颠倒字节序,将其改成大端排列。重排方法:

  // 翻转字节顺序 (16-bit)

    public static void ReverseBytes(byte[] value)

    {

        for (int i = 0; i < 6; i += 2)

        {

            byte byTemp = value[i];

            value[i] = value[i + 1];

            value[i + 1] = byTemp;

        }

}

原理就是将Data[0]和Data[1]互换,Data[2]和Data[3]互换。。。

  1. 再传给Encoding.Unicode.GetString()函数编码,发现正常了。

 

注意点:

  1. 无论大小端问题,还是编码问题,最小单位都是字节为单位。
  2. Unicode编码一般都是以2个字节为单位,也就是数据传过来都是2个字节一个模块,

大小端出问题也就是这两个字节排序是否乱了的问题。我之前将6个字节的Data使用Array.Reverse()重新排序了下,发现尴尬了,字符不乱码了,但是文字都倒过来了,“王力宏”变成了“宏力王”了。其实细想一下也对,这种方式将6个字节看做一个整体,将0和5对调, 1和4对调,等等。这样确实两个字节内部也颠倒了,但是总体也颠倒了。所以嘛,我总结后发现,只要两个字节就可以了。

好了,大小端问题先总结到这,一般大小端貌似在网络传输中用的多,暂时还没涉及,以后接触了再来补充。。。。

 

 

 

你可能感兴趣的:(c++基础)