大端小端区别:
举例:
一个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()
问题:出现乱码
原因:
- 调试时候查看,发现每次获取到的数据是6个字节,按照2个字节编码一个中文汉字习惯,那么别人给我的是3个汉字。
- 别人给我的数据是按照小端方式排列的,也就是说第一个汉字所占的两个字节数据Data[0]表示低字节数据,Data[1]表示高字节数据,然后我就直接传给API Encoding.Unicode.GetString()了,结果发现乱码。
解决措施:
- 查询网上资料后发现存在大小端问题,于是查看自己的机器编码方式,发现是大端。
- 于是乎自定义函数,颠倒字节序,将其改成大端排列。重排方法:
// 翻转字节顺序 (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]互换。。。
- 再传给Encoding.Unicode.GetString()函数编码,发现正常了。
注意点:
- 无论大小端问题,还是编码问题,最小单位都是字节为单位。
- Unicode编码一般都是以2个字节为单位,也就是数据传过来都是2个字节一个模块,
大小端出问题也就是这两个字节排序是否乱了的问题。我之前将6个字节的Data使用Array.Reverse()重新排序了下,发现尴尬了,字符不乱码了,但是文字都倒过来了,“王力宏”变成了“宏力王”了。其实细想一下也对,这种方式将6个字节看做一个整体,将0和5对调, 1和4对调,等等。这样确实两个字节内部也颠倒了,但是总体也颠倒了。所以嘛,我总结后发现,只要两个字节就可以了。
好了,大小端问题先总结到这,一般大小端貌似在网络传输中用的多,暂时还没涉及,以后接触了再来补充。。。。