字节序

编程技术  /  houtizong 发布于 3年前   76

作者:赵磊

博客:http://elf8848.iteye.com

 

字节序,顾名思义就是字节存放的顺序


字节序分为两种:

BIG-ENDIAN----大字节序

LITTLE-ENDIAN----小字节序


BIG-ENDIAN、LITTLE-ENDIAN与多字节类型的数据有关的比如int,short,long型,而对单字节数据byte却没有影响。

BIG-ENDIAN就是最低地址存放最高有效字节。

LITTLE-ENDIAN是最低地址存放最低有效字节。即常说的低位在先,高位在后。 


Java中int类型占4个字节,一定要是“多字节类型的数据”才有字节序问题,汉字编码也有这个问题。请看下面4字节的例子:


  比如 int a = 0x05060708 


  在BIG-ENDIAN的情况下存放为: 

  低地址------->高地址 

  字节号: 第0字节,第1字节,第2字节,第3字节 

  数  据: 05    , 06   , 07   , 08 


  在LITTLE-ENDIAN的情况下存放为: 

  低地址------->高地址 

  字节号: 第0字节,第1字节,第2字节,第3字节 

  数  据: 08    , 07   , 06   , 05 



JAVA字节序:

指的是在JAVA虚拟机中多字节类型数据的存放顺序,JAVA字节序也是BIG-ENDIAN。 


主机字节序:

Intel的x86系列CPU是Little-Endian,而PowerPC 、SPARC和Motorola处理器是BIG-ENDIAN。

ARM同时支持 big和little,实际应用中通常使用little endian。是BIG-ENDIAN还是LITTLE-ENDIAN的跟CPU有关的,每一种CPU不是BIG-ENDIAN就是LITTLE-ENDIAN。


网络字节序:

4个字节的32 bit值以下面的次序传输:首先是0~7bit,其次8~15bit,然后16~23bit,最后是24~31bit。这种传输次序称作大端字节序(BIG-ENDIAN)。 TCP/IP首部中所有的二进制整数在网络中传输时都要求以这种次序。


不同的CPU上运行不同的操作系统,字节序也是不同的,参见下表。

    处理器     操作系统   字节排序

    Alpha     全部        Little endian

    HP-PA     NT          Little endian

    HP-PA     UNIX        Big endian

    Intelx86  全部        Little endian



所以在用C/C++写通信程序时,在发送数据前务必用htonl和htons去把整型和短整型的数据进行从主机字节序到网络字节序的转换,而接收数据后对于整型和短整型数据则必须调用ntohl和ntohs实现从网络字节序到主机字节序的转换。如果通信的一方是JAVA程序、一方是C/C++程序时,则需要在C/C++一侧使用以上几个方法进行字节序的转换,而JAVA一侧,则不需要做任何处理,因为JAVA字节序与网络字节序都是BIG-ENDIAN,只要C/C++一侧能正确进行转换即可(发送前从主机序到网络序,接收时反变换)。如果通信的双方都是JAVA,则根本不用考虑字节序的问题了。 

 

java中转换字节序

 

方案一:通过ByteBuffer实现

ByteBuffer类中的order(ByteOrder bo) 方法可以设置 ByteBuffer 的字节序。 

 

其中的ByteOrder是枚举: 

ByteOrder BIG_ENDIAN  代表大字节序的 ByteOrder 。

ByteOrder LITTLE_ENDIAN  代表小字节序的 ByteOrder 。

ByteOrder nativeOrder()  返回当前硬件平台的字节序。

 

 

 

 

方案二:自己写代码实现(原自网络)

 

package com.xxx;/** * 通信格式转换 *  * Java和一些windows编程语言如c、c++、delphi所写的网络程序进行通讯时,需要进行相应的转换 高、低字节之间的转换 * windows的字节序为低字节开头 linux,unix的字节序为高字节开头 java则无论平台变化,都是高字节开头 */public class FormatTransfer {/** * 将int转为低字节在前,高字节在后的byte数组 *  * @param n *            int * @return byte[] */public static byte[] toLH(int n) {byte[] b = new byte[4];b[0] = (byte) (n & 0xff);b[1] = (byte) (n >> 8 & 0xff);b[2] = (byte) (n >> 16 & 0xff);b[3] = (byte) (n >> 24 & 0xff);return b;}/** * 将int转为高字节在前,低字节在后的byte数组 *  * @param n *            int * @return byte[] */public static byte[] toHH(int n) {byte[] b = new byte[4];b[3] = (byte) (n & 0xff);b[2] = (byte) (n >> 8 & 0xff);b[1] = (byte) (n >> 16 & 0xff);b[0] = (byte) (n >> 24 & 0xff);return b;}/** * 将short转为低字节在前,高字节在后的byte数组 *  * @param n *            short * @return byte[] */public static byte[] toLH(short n) {byte[] b = new byte[2];b[0] = (byte) (n & 0xff);b[1] = (byte) (n >> 8 & 0xff);return b;}/** * 将short转为高字节在前,低字节在后的byte数组 *  * @param n *            short * @return byte[] */public static byte[] toHH(short n) {byte[] b = new byte[2];b[1] = (byte) (n & 0xff);b[0] = (byte) (n >> 8 & 0xff);return b;}/** * 将将int转为高字节在前,低字节在后的byte数组 public static byte[] toHH(int number) { int * temp = number; byte[] b = new byte[4]; for (int i = b.length - 1; i > -1; * i--) { b = new Integer(temp & 0xff).byteValue(); temp = temp >> 8; } * return b; } public static byte[] IntToByteArray(int i) { byte[] abyte0 = * new byte[4]; abyte0[3] = (byte) (0xff & i); abyte0[2] = (byte) ((0xff00 & * i) >> 8); abyte0[1] = (byte) ((0xff0000 & i) >> 16); abyte0[0] = (byte) * ((0xff000000 & i) >> 24); return abyte0; } *//** * 将float转为低字节在前,高字节在后的byte数组 */public static byte[] toLH(float f) {return toLH(Float.floatToRawIntBits(f));}/** * 将float转为高字节在前,低字节在后的byte数组 */public static byte[] toHH(float f) {return toHH(Float.floatToRawIntBits(f));}/** * 将String转为byte数组 */public static byte[] stringToBytes(String s, int length) {while (s.getBytes().length < length) {s += " ";}return s.getBytes();}/** * 将字节数组转换为String *  * @param b *            byte[] * @return String */public static String bytesToString(byte[] b) {StringBuffer result = new StringBuffer("");int length = b.length;for (int i = 0; i < length; i++) {result.append((char) (b[i] & 0xff));}return result.toString();}/** * 将字符串转换为byte数组 *  * @param s *            String * @return byte[] */public static byte[] stringToBytes(String s) {return s.getBytes();}/** * 将高字节数组转换为int *  * @param b *            byte[] * @return int */public static int hBytesToInt(byte[] b) {int s = 0;for (int i = 0; i < 3; i++) {if (b[i] >= 0) {s = s + b[i];} else {s = s + 256 + b[i];}s = s * 256;}if (b[3] >= 0) {s = s + b[3];} else {s = s + 256 + b[3];}return s;}/** * 将低字节数组转换为int *  * @param b *            byte[] * @return int */public static int lBytesToInt(byte[] b) {int s = 0;for (int i = 0; i < 3; i++) {if (b[3 - i] >= 0) {s = s + b[3 - i];} else {s = s + 256 + b[3 - i];}s = s * 256;}if (b[0] >= 0) {s = s + b[0];} else {s = s + 256 + b[0];}return s;}/** * 高字节数组到short的转换 *  * @param b *            byte[] * @return short */public static short hBytesToShort(byte[] b) {int s = 0;if (b[0] >= 0) {s = s + b[0];} else {s = s + 256 + b[0];}s = s * 256;if (b[1] >= 0) {s = s + b[1];} else {s = s + 256 + b[1];}short result = (short) s;return result;}/** * 低字节数组到short的转换 *  * @param b *            byte[] * @return short */public static short lBytesToShort(byte[] b) {int s = 0;if (b[1] >= 0) {s = s + b[1];} else {s = s + 256 + b[1];}s = s * 256;if (b[0] >= 0) {s = s + b[0];} else {s = s + 256 + b[0];}short result = (short) s;return result;}/** * 高字节数组转换为float *  * @param b *            byte[] * @return float */public static float hBytesToFloat(byte[] b) {int i = 0;Float F = new Float(0.0);i = ((((b[0] & 0xff) << 8 | (b[1] & 0xff)) << 8) | (b[2] & 0xff)) << 8 | (b[3] & 0xff);return F.intBitsToFloat(i);}/** * 低字节数组转换为float *  * @param b *            byte[] * @return float */public static float lBytesToFloat(byte[] b) {int i = 0;Float F = new Float(0.0);i = ((((b[3] & 0xff) << 8 | (b[2] & 0xff)) << 8) | (b[1] & 0xff)) << 8 | (b[0] & 0xff);return F.intBitsToFloat(i);}/** * 将byte数组中的元素倒序排列 */public static byte[] bytesReverseOrder(byte[] b) {int length = b.length;byte[] result = new byte[length];for (int i = 0; i < length; i++) {result[length - i - 1] = b[i];}return result;}/** * 打印byte数组 */public static void printBytes(byte[] bb) {int length = bb.length;for (int i = 0; i < length; i++) {System.out.print(bb + " ");}System.out.println("");}public static void logBytes(byte[] bb) {int length = bb.length;String out = "";for (int i = 0; i < length; i++) {out = out + bb + " ";}}/** * 将int类型的值转换为字节序颠倒过来对应的int值 *  * @param i *            int * @return int */public static int reverseInt(int i) {int result = FormatTransfer.hBytesToInt(FormatTransfer.toLH(i));return result;}/** * 将short类型的值转换为字节序颠倒过来对应的short值 *  * @param s *            short * @return short */public static short reverseShort(short s) {short result = FormatTransfer.hBytesToShort(FormatTransfer.toLH(s));return result;}/** * 将float类型的值转换为字节序颠倒过来对应的float值 *  * @param f *            float * @return float */public static float reverseFloat(float f) {float result = FormatTransfer.hBytesToFloat(FormatTransfer.toLH(f));return result;}}
 

 

 

上一篇:MVC5
下一篇:Java 高级知识

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!

留言需要登陆哦

技术博客集 - 网站简介:
前后端技术:
后端基于Hyperf2.1框架开发,前端使用Bootstrap可视化布局系统生成

网站主要作用:
1.编程技术分享及讨论交流,内置聊天系统;
2.测试交流框架问题,比如:Hyperf、Laravel、TP、beego;
3.本站数据是基于大数据采集等爬虫技术为基础助力分享知识,如有侵权请发邮件到站长邮箱,站长会尽快处理;
4.站长邮箱:[email protected];

      订阅博客周刊 去订阅

文章归档

文章标签

友情链接

Auther ·HouTiZong
侯体宗的博客
© 2020 zongscan.com
版权所有ICP证 : 粤ICP备20027696号
PHP交流群 也可以扫右边的二维码
侯体宗的博客