文档章节

字节序

猪刚烈
 猪刚烈
发布于 2014/09/24 13:52
字数 1876
阅读 9
收藏 0

作者:赵磊

博客: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;
	}
}
 

 

 

本文转载自:http://elf8848.iteye.com/blog/1506471

猪刚烈
粉丝 22
博文 708
码字总数 110
作品 1
海淀
程序员
私信 提问
大小字节序的深入理解和鉴定系统字节序方法

最近在项目中的soket通信时,遇到了大小字节序问题和网络传输时的字节序问题,现在给大家整理一下,希望大家对字节序有个比较深入的了解,其实理解了就很简单的。 开始遇到的问题: 1、本地的...

沙米笔记
2016/03/26
759
3
网络字节序与主机字节序的转换

在对IP地址结构体SOCKADDR_IN赋值的时候,经常会用到下列的函数htonl,htons,inet_addr,与之相对应的函数是ntohl,ntohs,inet_ntoa。查看这些函数的解析,会发现这些函数其实是与主机字节序和网...

长平狐
2013/01/06
132
0
最简单的方式教你理解大小端字节序

学过编程的人都应该知道大小端字节序的概念,但是很多时候,总是把他们弄混,这是整理出来的一份很简单的方式理解字节序的文章,废话不多说,这里直接入正题。 什么是字节序? 字节序,简单来...

暮回_梓
2018/06/26
0
0
理解字节序

1. 计算机硬件有两种储存数据的方式:大端字节序(big endian)和小端字节序(little endian)。 举例来说,数值使用两个字节储存:高位字节是,低位字节是。 大端字节序:高位字节在前,低位...

阮一峰
2016/11/22
0
0
字节序和大小端

字节顺序 字节顺序(Endian) 字节序是指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序。 计算机系统一般采用字节(Byte(8 bit ))作为逻辑寻址单位。当物理单位的长度大于1个字...

子韦一
2013/12/25
376
0

没有更多内容

加载失败,请刷新页面

加载更多

面向对象编程

1、类和对象 类是对象的蓝图和模板,而对象是实例;即对象是具体的实例,类是一个抽象的模板 当我们把一大堆拥有共同特征的对象的静态特征(属性)和动态特征(行为)都抽取出来后,就可以定...

huijue
今天
8
0
redis异常解决 :idea启动本地redis出现 jedis.exceptions.JedisDataException: NOAUTH Authentication required

第一次安装在本地redis服务,试试跑项目,结果却出现nested exception is redis.clients.jedis.exceptions.JedisDataException: NOAUTH Authentication required错误,真是让人头疼 先检查一...

青慕
今天
12
0
Spring 之 IoC 源码分析 (基于注解方式)

一、 IoC 理论 IoC 全称为 Inversion of Control,翻译为 “控制反转”,它还有一个别名为 DI(Dependency Injection),即依赖注入。 二、IoC方式 Spring为IoC提供了2种方式,一种是基于xml...

星爵22
今天
25
0
Docker安装PostgresSql

Docker安装PostgresSql 拉取docker镜像 # docker pull postgres:10.1010.10: Pulling from library/postgres9fc222b64b0a: Pull complete 38296355136d: Pull complete 2809e135bbdb: Pu......

Tree
今天
8
0
内容垂直居中

方法一: 采用上下 padding 形式,将内容放置在垂直居中 .line { padding: 2% 0; text-align: center; height: 5px;} <div class="line"> 内容垂直居中</div> 方法二: 采......

低至一折起
今天
20
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部