Byte大小端模式

什么是大小端

大端模式

高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放。

小端模式

高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。

这两种模式,泥瓦匠记忆宫殿:“小端低低”。这样就知道小端的模式,反之大端的模式。
比如,整形十进制数字305419896 ,转化为十六进制表示0x12345678。其中按着十六进制的话,每字符占8个位,1字节。

为什么有大小端之分

在操作系统中,x86和一般的OS(如windows,FreeBSD,Linux)使用的是小端模式。但比如Mac OS是大端模式。
在计算机系统中,是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器)。另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如果将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。
知道为什么有模式的存在,下面需要了解下具有有什么应用场景。

  • 不同端模式的处理器进行数据传递时必须要考虑端模式的不同。
  • 在网络上传输数据时,由于数据传输的两端对应不同的硬件平台,采用的存储字节顺序可能不一致。所以在TCP/IP协议规定了在网络上必须采用网络字节顺序,也就是大端模式。对于char型数据只占一个字节,无所谓大端和小端。而对于非char类型数据,必须在数据发送到网络上之前将其转换成大端模式。接收网络数据时按符合接受主机的环境接收。

    Java中的大小端

    存储量大于1字节,非char类型,如intfloat等,要考虑字节的顺序问题了。Java由于虚拟机的关系,屏蔽了大小端问题,需要知道的话可用ByteOrder.nativeOrder()查询。在操作ByteBuffer中,也可以使用 ByteBuffer.order()进行设置。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    package memory;
    import java.nio.ByteBuffer;
    import java.nio.ByteOrder;
    import java.util.Arrays;
    public class Endians {
    public static void main(String[] args) {
    // 创建12个字节的字节缓冲区
    ByteBuffer bb = ByteBuffer.wrap(new byte[12]);
    // 存入字符串
    bb.asCharBuffer().put("abdcef");
    System.out.println(Arrays.toString(bb.array()));
    // 反转缓冲区
    bb.rewind();
    // 设置字节存储次序,大端模式
    bb.order(ByteOrder.BIG_ENDIAN);
    bb.asCharBuffer().put("abcdef");
    System.out.println(Arrays.toString(bb.array()));
    // 反转缓冲区
    bb.rewind();
    // 设置字节存储次序,小端模式
    bb.order(ByteOrder.LITTLE_ENDIAN);
    bb.asCharBuffer().put("abcdef");
    System.out.println(Arrays.toString(bb.array()));
    }
    }
1
2
3
[0, 97, 0, 98, 0, 100, 0, 99, 0, 101, 0, 102]
[0, 97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102]
[97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102, 0]

前两句打印说明了,ByteBuffer存储字节次序默认为大端模式。最后一段设置了字节存储次序,然后会输出,可以看出存储次序为小端模式。

Byte转换工具

byte转换工具,用到大小端模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
package com.mallcoo.util;
import java.nio.ByteOrder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* byte转换工具类
*
* @Title: ByteUtil.java
* @Package com.mallcoo.radius.util
* @Description:
* @author yujie@mallcoo.cn
* @date 2013-10-1 下午4:43:13
* @version V1.0
* @jdk jdk1.6.0_45
*/
public class ByteUtil {
public static final Log log = LogFactory.getLog(ByteUtil.class);
/**
* int转换成byte[4]
*
* @Title: intTobyte
* @author : yujie@mallcoo.cn
* @Description: int转换byte[4],byte长度4的
* @param value
* 整形
* @param order
* 字节排序 big endian:(高位优先)将最重要的字节存放在地址最低的存储器单元 ->0 big
* littel_endian: (低位优先)则是将最重要的字节放在地址最高的存储器单元 0->
* @return byte[] 长度=4
*
*/
public static byte[] intToByte(int value, ByteOrder order) {
byte[] tmp = new byte[4];
if (order == ByteOrder.BIG_ENDIAN) {
tmp[0] = (byte) (value >>> 24);
tmp[1] = (byte) (value >>> 16);
tmp[2] = (byte) (value >>> 8);
tmp[3] = (byte) value;
/*
* for (int i = 3; i >= 0; i--) { b[i] = new
* Integer(value).byteValue(); // 向右移8位 value = value >> 8; }
*
* for(int i=0; i<4; i++){    b[i]=(byte)(value>>8*(3-i));    }
*/
} else {
tmp[0] = (byte) value;
tmp[1] = (byte) (value >>> 8);
tmp[2] = (byte) (value >>> 16);
tmp[3] = (byte) (value >>> 24);
/*
* for (int i = 0; i < 4; i++) { b[i] = new
* Integer(value).byteValue(); // 向右移8位 value = value >> 8; }
*
* for(int i=3; i>=0; i--){    b[i]=(byte)(value>>8 * i);    }
*/
}
return tmp;
}
/**
* short转换成byte[2]
*
* @Title: shortTobyte
* @author : yujie@mallcoo.cn
* @Description: short转换byte[2],byte长度2的
* @param value
* 整形
* @param order
* 字节排序 big endian:(高位优先)将最重要的字节存放在地址最低的存储器单元 big littel_endian:
* (低位优先)则是将最重要的字节放在地址最高的存储器单元
* @return byte[] 长度=2
*
*/
public static byte[] shortToByte(short value, ByteOrder order) {
byte[] tmp = new byte[2];
if (order == ByteOrder.BIG_ENDIAN) {
tmp[0] = (byte) (value >>> 8);
tmp[1] = (byte) (value);
/*
* for (int i = 1; i >= 0; i--) { b[i] = new
* Integer(value).byteValue(); // 向右移8位 value = value >> 8; }
* for(int i=0; i<2; i++){    b[i]=(byte)(value>>8*(1-i));    }
*/
} else {
tmp[0] = (byte) (value);
tmp[1] = (byte) (value >>> 8);
/*
* for (int i = 0; i < 2; i++) { b[i] = new
* Integer(value).byteValue(); // 向右移8位 value = value >> 8; }
*
* for(int i=1; i>=0; i--){    b[i]=(byte)(value >> 8 * i);    }
*/
}
return tmp;
}
/**
* long转byte[8]
*
* @Title: longTobyte
* @author : yujie@mallcoo.cn
* @Description: long转换byte[8],byte长度8的
* @param value
* 整形
* @param order
* 字节排序 big endian:(高位优先)将最重要的字节存放在地址最低的存储器单元 big littel_endian:
* (低位优先)则是将最重要的字节放在地址最高的存储器单元
* @return byte[] 长度=8
*
*/
public static byte[] longToByte(long value, ByteOrder order) {
byte[] tmp = new byte[8];
if (order == ByteOrder.BIG_ENDIAN) {
tmp[7] = (byte) value;
tmp[6] = (byte) (value >>> 8);
tmp[5] = (byte) (value >>> 16);
tmp[4] = (byte) (value >>> 24);
tmp[3] = (byte) (value >>> 32);
tmp[2] = (byte) (value >>> 40);
tmp[1] = (byte) (value >>> 48);
tmp[0] = (byte) (value >>> 56);
/*
* for (int i = 7; i >= 0; i--) { b[i] = new
* Integer(value).byteValue(); // 向右移8位 value = value >> 8; }
* for(int i=0; i<8; i++){    b[i]=(byte)(value>>8*(7-i));    }
*/
} else {
tmp[0] = (byte) value;
tmp[1] = (byte) (value >>> 8);
tmp[2] = (byte) (value >>> 16);
tmp[3] = (byte) (value >>> 24);
tmp[4] = (byte) (value >>> 32);
tmp[5] = (byte) (value >>> 40);
tmp[6] = (byte) (value >>> 48);
tmp[7] = (byte) (value >>> 56);
/*
* for (int i = 0; i < 8; i++) { b[i] = new
* Integer(value).byteValue(); // 向右移8位 value = value >> 8; }
*
* for(int i=7; i>=0; i--){    b[i]=(byte)(value>>8 * i);    }
*/
}
return tmp;
}
/*public byte[] floatToByte(float value, ByteOrder order) {

}


public byte[] byteToFloat(byte[] value, ByteOrder order) {

}*/

/**
* byte[4] 转换 int
*
* @Title: byteToInt
* @author : yujie@mallcoo.cn
* @Description: byte[4] 转换 int
* @param value
* 长度是4的字节
* @param order
* 字节排序 big endian:(高位优先)将最重要的字节存放在地址最低的存储器单元 big
* littel_endian:(低位优先)则是将最重要的字节放在地址最高的存储器单元
* @return int
* @throws 数组越界
*/
public static int byteToInt(byte[] value, ByteOrder order) throws IndexOutOfBoundsException {
// 字节数组越界
if (value.length > 4) {
log.info("字节数组越界!");
throw new IndexOutOfBoundsException();
}
int tmp = 0;
// big endian(高位优先)将最重要的字节存放在地址最低的存储器单元
if (order == ByteOrder.BIG_ENDIAN) {
tmp += (value[0] & 0xFF) << 24;
tmp += (value[1] & 0xFF) << 16;
tmp += (value[2] & 0xFF) << 8;
tmp += value[3] & 0xFF;
/*
*
* for(int i=0; i<4; i++){ //高位都是1,所以需要&255或者&0xff,把高位的1去掉;然后在位移   
* intValue +=(b[i] & 0xFF)<<(8*(3-i));    }
*/
} else {// (低位优先)则是将最重要的字节放在地址最高的存储器单元
tmp += value[0] & 0xFF;
tmp += (value[1] & 0xFF) << 8;
tmp += (value[2] & 0xFF) << 16;
tmp += (value[3] & 0xFF) << 24;
/*
*
* for(int i=3; i >= 0; i--){ //高位都是1,所以需要&255或者&0xff,把高位的1去掉;然后在位移
*    intValue +=(b[i] & 0xFF)<<(8 * i);    }
*/
}
return tmp;
}
/**
* byte[2] 转换 short
*
* @Title: byteToShort
* @author : yujie@mallcoo.cn
* @Description: byte[2] 转换 short
* @param value
* 长度是2的字节
* @param order
* 字节排序 big endian:(高位优先)将最重要的字节存放在地址最低的存储器单元 big
* littel_endian:(低位优先)则是将最重要的字节放在地址最高的存储器单元
* @return short
* @throws IndexOutOfBoundsException
* 数组越界
*
*/
public static short byteToShort(byte[] value, ByteOrder order) throws IndexOutOfBoundsException {
if (value.length > 2) {
log.info("字节数组越界!");
throw new IndexOutOfBoundsException();
}
int tmp = 0;
// big endian(高位优先)将最重要的字节存放在地址最低的存储器单元
if (order == ByteOrder.BIG_ENDIAN) {
tmp += (value[0] & 0xFF) << 8;
tmp += value[1] & 0xFF;
/*
*
* for(int i=0; i<2; i++){ //高位都是1,所以需要&255或者&0xff,把高位的1去掉;然后在位移   
* intValue +=(b[i] & 0xFF)<<(8*(1-i));    }
*/
} else {// (低位优先)则是将最重要的字节放在地址最高的存储器单元
tmp += (value[1] & 0xFF) << 8;
tmp += value[0] & 0xFF;
/*
*
* for(int i=1; i >= 0; i--){ //高位都是1,所以需要&255或者&0xff,把高位的1去掉;然后在位移
*    intValue +=(b[i] & 0xFF)<<(8 * i);    }
*/
}
return (short) tmp;
}
/**
* byte[8] 转换 long
*
* @Title: byteToLong
* @author : yujie@mallcoo.cn
* @Description: byte[8] 转换 long
* @param value
* 长度是8的字节
* @param order
* 字节排序 big endian:(高位优先)将最重要的字节存放在地址最低的存储器单元 big littel_endian:
* (低位优先)则是将最重要的字节放在地址最高的存储器单元
* @return long
* @throws IndexOutOfBoundsException
* 数组越界
*
*/
public static long byteToLong(byte[] value, ByteOrder order) throws IndexOutOfBoundsException {
if (value.length > 8) {
log.info("字节数组越界!");
throw new IndexOutOfBoundsException();
}
long tmp = 0;
// big endian(高位优先)将最重要的字节存放在地址最低的存储器单元
if (order == ByteOrder.BIG_ENDIAN) {
tmp += (value[0] & 0xFF) << 56;
tmp += (value[1] & 0xFF) << 48;
tmp += (value[2] & 0xFF) << 40;
tmp += (value[3] & 0xFF) << 32;
tmp += (value[4] & 0xFF) << 24;
tmp += (value[5] & 0xFF) << 16;
tmp += (value[6] & 0xFF) << 8;
tmp += (value[7] & 0xFF);
/*
*
* for(int i=0; i<8; i++){ //高位都是1,所以需要&255或者&0xff,把高位的1去掉;然后在位移   
* intValue +=(b[i] & 0xFF)<<(8*(7-i));    }
*/
} else {// (低位优先)则是将最重要的字节放在地址最高的存储器单元
tmp += value[0] & 0xFF;
tmp += (value[1] & 0xFF) << 8;
tmp += (value[2] & 0xFF) << 16;
tmp += (value[3] & 0xFF) << 24;
tmp += (value[4] & 0xFF) << 32;
tmp += (value[5] & 0xFF) << 40;
tmp += (value[6] & 0xFF) << 48;
tmp += (value[7] & 0xFF) << 56;
/*
*
* for(int i=7; i >= 0; i--){ //高位都是1,所以需要&255或者&0xff,把高位的1去掉;然后在位移
*    intValue +=(b[i] & 0xFF)<<(8 * i);    }
*/
}
return tmp;
}

/**
* 浮点转换为字节
*
* @param f
* @return
*/
public static byte[] floatToByte(float f) {

// 把float转换为byte[]
int fbit = Float.floatToIntBits(f);

byte[] b = new byte[4];
for (int i = 0; i < 4; i++) {
b[i] = (byte) (fbit >> (24 - i * 8));
}

// 翻转数组
int len = b.length;
// 建立一个与源数组元素类型相同的数组
byte[] dest = new byte[len];
// 为了防止修改源数组,将源数组拷贝一份副本
System.arraycopy(b, 0, dest, 0, len);
byte temp;
// 将顺位第i个与倒数第i个交换
for (int i = 0; i < len / 2; ++i) {
temp = dest[i];
dest[i] = dest[len - i - 1];
dest[len - i - 1] = temp;
}

return dest;

}

/**
* 字节转换为浮点
*
* @param b 字节(至少4个字节)
* @param index 开始位置
* @return
*/
public static float byteToFloat(byte[] b, int index) {
int l;
l = b[index + 0];
l &= 0xff;
l |= ((long) b[index + 1] << 8);
l &= 0xffff;
l |= ((long) b[index + 2] << 16);
l &= 0xffffff;
l |= ((long) b[index + 3] << 24);
return Float.intBitsToFloat(l);
}


/**
* 将byte转换为一个长度为8的byte数组,数组每个值代表bit;&操作,如果结果是0 那么这一位的2进制就是0,否则就是1
*/
public static byte[] byteToArrayBit(byte b) {
byte[] array = new byte[8];
for (int i = 7; i >= 0; i--) {
array[i] = (byte) (b & 1);
b = (byte) (b >> 1); // 下一位
}
return array;
}
/**
* 把byte转为字符串的bit;&操作,如果结果是0 那么这一位的2进制就是0,否则就是1
*/
public static String byteToBit(byte b) {
return "" + (byte) ((b >> 7) & 0x1) + (byte) ((b >> 6) & 0x1) + (byte) ((b >> 5) & 0x1) + (byte) ((b >> 4) & 0x1) + (byte) ((b >> 3) & 0x1)
+ (byte) ((b >> 2) & 0x1) + (byte) ((b >> 1) & 0x1) + (byte) ((b >> 0) & 0x1);
}
/**
* 二进制字符串转byte
*/
public static byte binaryToByte(String byteStr) {
int b, len;
if (null == byteStr) {
return 0;
}
len = byteStr.length();
if (len != 4 && len != 8) {
return 0;
}
if (len == 8) {// 8 bit处理
if (byteStr.charAt(0) == '0') {// 正数
b = Integer.parseInt(byteStr, 2);
} else {// 负数
b = Integer.parseInt(byteStr, 2) - 256;
}
} else {// 4 bit处理
b = Integer.parseInt(byteStr, 2);
}
return (byte) b;
}


public static void main(String[] args) {
//高位->低位
/*byte[] aa={0,0,0,123};
System.out.println(ByteUtil.byteToInt(aa, ByteOrder.BIG_ENDIAN));
-------------------------------------------------------------------------*/

//测试float 转 byte
byte[] v=ByteUtil.floatToByte(1.0f);
for (int i = 0; i < v.length; i++) {
System.out.print(v[i]+" ");
}

System.out.println();

byte[] b = { 0, 0, -128, 63 };
System.out.println(ByteUtil.byteToFloat(b, 0));
}
}
# Java

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×