两个例子理解主机字节序和网络字节序,不同平台字节序转换
2017-09-10 18:53
513 查看
不同平台存储多字节整形数据的内存顺序不同,分为主机字节序和网络字节序分别对应小端字节序和大端字节序
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类型。
输出为:00002710
查看内存,排序为10270000
定义一个byte数组 {0x01,0x00,0x00,0x00},分别查看不同平台下转为int时的值
工具方法:
int转byte数组
byte数组转int
API使用陷阱:
用OutputStream 的write(int)方法时要注意:
将指定的字节写入此输出流。write 的常规协定是:向输出流写入一个字节。
要写入的字节是参数 b 的八个低位。b 的 24 个高位将被忽略。
比如 传入int 1000,内存占位状态[0, 0, 39, 16],1000的八个低位即为16
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类型。
举两个例子来理解一下
定义一个int值10000,分别查看在不同平台下的内存排序//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
定义一个byte数组 {0x01,0x00,0x00,0x00},分别查看不同平台下转为int时的值
//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
相关文章推荐
- API SOCKET基础(三)网络字节序与主机字节序的转换
- 测试平台大端还是小端(网络字节序和主机字节序)
- C语言学习4: 函数返回值与传入参数,关于函数值传递和类型隐性转换,变量不同的作用域,static变量,多文件编译例如两个C文件,显示函数调用语句跳转,递归,斐波那契数列,多文件编译相同变量的问题。
- 关于网络字节序和主机字节序的转换
- 安卓平台ARM Mali OpenCL例子-灰度转换
- 网络字节序 主机字节序 转换
- 通过两个例子来理解js中的命令模式
- 网络字节序与主机字节序的转换[转]
- 主机字节序与网络字节序的转换过程
- 不同平台间的换行符转换
- 网络字节序与主机字节序的转换
- Java字节序(不同语言中的网络数据传输时字节序列转换)
- 网络字节序与主机字节序的转换
- 不同进制间的相互转换的理解
- 网络字节序与主机字节序的转换
- Java字节序,java整型数与网络字节序 byte[] 数组转换关系(ByteArrayOutputStream用法)
- 多操作系统平台协同开发时 GIT 的注意事项: 不同操作系统中的换行符(不要使用git的换行符自动转换功能,并且,尽可能保证代码的换行符都是unix); 避免使用第三方插件(如 EGit );
- [转]多操作系统平台协同开发时 GIT 的注意事项: 不同操作系统中的换行符(不要使用git的换行符自动转换功能,并且,尽可能保证代码的换行符都是unix); 避免使用第三方插件(如 EGit );
- 形参和实参理解 数组指针的两个例子
- 2018.4.1(python)温度的刻画有两个不同体系:摄氏度(Celsius)和华氏度(Fabrenheit)。 请编写程序将用户输入华氏度转换为摄氏度,或将输入的摄氏度转换为华氏度。