大小端与序列化
2012 年 3 月 24 日
进制 | 表示 | 高位 | 低位 |
---|---|---|---|
十进制 | 4660 | 4 | 0 |
十六进制 | 0x1234 | 12 | 34 |
二进制 | 0001001000110100 | 0001 | 0100 |
现代的阅读/书写习惯大都是从左向右,这是 大端
(Big-endian):
在低地址中存高位内容
0x001 | 0x002 |
---|---|
00010010 | 00110100 |
机器中以二进制存储数数据,从低位到高位处理,这是 小端
(Little-endian):
在低地址中存低位内容
0x001 | 0x002 |
---|---|
00110100 | 00010010 |
以int类型的整数 65535 为例:
int 类型在内存中占4字节/32位,定义一个长度为4的数组存储序列化的内容(数组在内存空间的地址是连续的):
- 大端
int num65535 = 0xFFFF; // 序列化 var bytes = new byte[]{0, 0, (byte) 0xFF, (byte) 0xFF}; // 反序列化 int num = (bytes[0] & 0xFF << 24) | (bytes[1] & 0xFF << 16) | (bytes[2] & 0xFF << 8) | (bytes[3] & 0xFF) assert num65535 == num;
- 小端
int num61695 = 0xF0FF; // 序列化 var bytes = new byte[]{(byte) 0xFF, (byte) 0xF0, 0, 0}; // 反序列化 int num = (bytes[0] & 0xFF) | (bytes[1] & 0xFF << 8) | (bytes[2] & 0xFF << 16) | (bytes[3] & 0xFF << 24); assert num65535 == num;
不同的序列化框架会选择不同的模式,比如protobuf用的是小端模式,TCP/IP的网络流用的是大端模式,在读取时转换即可。