不同平台存储多字节整形数据的内存顺序不同,分为主机字节序和网络字节序分别对应小端字节序和大端字节序
Java平台存储多字节整形时是大端字节序,如存储int i=0x01020304 在内存中的顺序是 01 02 03 04。先占位高内存,后占位低内存。即数值的高位存储在低内存上
c++ windows平台下是低端字节序 int i=0x01020304 在内存中的顺序是 04 03 02 01。先占位低内存后占位高内存,即数值的高位存储在高内存上
网络和JVM都采用的是大字节序,这种字节序符合人类的习惯。JVM会根据底层的操作系统和CPU自动进行字节序的转换
int i= 0x01020304在Java平台上存储顺序是01 02 03 04,发送后c+ +平台接收到的顺序是01 02 03 04 放到内存中的顺序也是 01 02 03 04,但是在c+ +平台识别 01 02 03 04 代表的int时,是以按照 int j = 0x04 03 02 01 按这个顺序拼好的数将这四字节内存识别为int类型。
//java平台下:
public static void main(String args[]) {
private static final char[] HEX_CHAR = {'0','1','2','3','4','5','6','7','8','9','a','b', 'c', 'd', 'e', 'f'};
int x = 10000;
//用ByteBuffer类将int转为byte数组,这种情况下是按照实际内存中的字节顺序输出,也就是大端字节序
//bb.order(ByteOrder.LITTLE_ENDIAN);此方法可以将输出的数组由大端字节序转为小端字节序排列
ByteBuffer bb = ByteBuffer.wrap(new byte[4]);
bb.asIntBuffer().put(x);
String hex = bytesToHexFun1(bb.array());
System.out.println(hex);
}
//byte数组转十六进制字符串
public static String bytesToHex(byte[] bytes) {
char[] buf = new char[bytes.length * 2];
int a = 0;
int index = 0;
for (byte b : bytes) {
if (b < 0) {
a = 256 + b;
} else {
a = b;
}
buf[index++] = HEX_CHAR[a / 16];
buf[index++] = HEX_CHAR[a % 16];
}
return new String(buf);
}
输出为:00002710
//c++平台下
int i = 10000;
char c[10];
memcpy(c,&i,sizeof(i));
查看内存,排序为10270000
//Java平台下:
byte [] b = {0x01,0x00,0x00,0x00};
int i = byteArrayToInt(b);
System.out.println(i+"");
//是以00000001 00000000 00000000 00000000 输出的i为16777216
//c++平台下:
char c[4] ={0x01,0x00,0x00,0x00};
int* p = (int*)c;//强转
int i=*p;
//是以00000000 00000000 00000000 00000001 输出的i为1
工具方法:
//利用ByteBuffer查看字节序
int x = 10000;
ByteBuffer bb = ByteBuffer.wrap(new byte[4]);
bb.asIntBuffer().put(x);
String ss_before = Arrays.toString(bb.array());
System.out.println("默认字节序 " + bb.order().toString() + "," + " 内存数据 "+ ss_before);
bb.order(ByteOrder.LITTLE_ENDIAN);
bb.asIntBuffer().put(x);
String ss_after = Arrays.toString(bb.array());
System.out.println("修改字节序 " + bb.order().toString() + "," + " 内存数据 "+ ss_after);
int转byte数组
//将int转为按低端字节序排列的byte数组(c++内存存放顺序)
public static byte[] int2ByteArray(int res) {
byte[] targets = new byte[4];
targets[0] = (byte) (res & 0xff);
targets[1] = (byte) ((res >> 8) & 0xff);
targets[2] = (byte) ((res >> 16) & 0xff);
targets[3] = (byte) (res >>> 24);
return targets;
}
//将int转为高端字节序排列的byte数组(Java内存存放顺序)
public static byte[] int2ByteArray(int n) {
byte[] byteArray = null;
try {
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
DataOutputStream dataOut = new DataOutputStream(byteOut);
dataOut.writeInt(n);
byteArray = byteOut.toByteArray();
Arrays.toString(byteArray);
} catch (IOException e) {
e.printStackTrace();
}
return byteArray;
}
//Java API 函数
public final void writeInt(int v) throws IOException {
out.write((v >>> 24) & 0xFF);
out.write((v >>> 16) & 0xFF);
out.write((v >>> 8) & 0xFF);
out.write((v >>> 0) & 0xFF);
incCount(4);
}
byte数组转int
//按低端字节序转int
public static int byteArray2Int(byte[] res) {
int targets = (res[0] & 0xff) | ((res[1] << 8) & 0xff00)| ((res[2] << 24) >>> 8) | (res[3] << 24);
return targets;
}
//按高端字节序转int
public static int byteArrayToInt(byte[] byteArray) {
int n = 0;
try {
ByteArrayInputStream byteInput = new ByteArrayInputStream(byteArray);
DataInputStream dataInput = new DataInputStream(byteInput);
n = dataInput.readInt();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return n;
}
//Java API 函数
public final int readInt() throws IOException {
int ch1 = in.read();
int ch2 = in.read();
int ch3 = in.read();
int ch4 = in.read();
if ((ch1 | ch2 | ch3 | ch4) < 0)
throw new EOFException();
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}
API使用陷阱:
用OutputStream 的write(int)方法时要注意:
将指定的字节写入此输出流。write 的常规协定是:向输出流写入一个字节。
要写入的字节是参数 b 的八个低位。b 的 24 个高位将被忽略。
比如 传入int 1000,内存占位状态[0, 0, 39, 16],1000的八个低位即为16