近期在写C++ socket和java socket之间的通信程序,涉及到整数浮点数的传输。须要从字节数组还原数据,查了一些资料。总结例如以下

1.       整数和浮点数的机器表示

在机器内部。不论是一个整数还是浮点数。都是以一个二进制串的形式存储。

整数可能是原码。补码表示,浮点数有阶码尾数两部分构成。不管如何都是一个二进制串。可是这个二进制串如何表示不同的机器可能採取不同的方案。

关于浮点数:

一个机器上的32位浮点数的二进制串在还有一个机器把它作为32位浮点数解释时可能得到不同的值,这样不同机器上进行网络传输的时候,大概就仅仅能用传字符串的方式了。只是幸好。IEEE 754规范标准化了浮点数的表示形式。遵从这个标准的不同编程语言里仅仅要遵从这个标准,那么某个浮点数的32位二进制串都是一样的,,,和CPU无关,和语言无关

关于整数 :

    单个字节的整型值就是一个字节;占用多个字节的整数,其表示有所差别,有所谓的小端法。大端法,详细表示能够看以下的图。

2.      小端法、大端法和主机字节顺序、网络字节顺序

小端法和大端法如图所看到的

 

网络字节序就是大端顺序,由于TCP/IP首部中全部的二进制整数在网络中传输时都要求以这样的次序,因此它又称作网络字节序。

主机字节顺序就是指相对于网络传输是的字节顺序的主机上的字节顺序。有大端表示法,小端表示法。

 

3.      以下给出java中的基本数据类型和字节数组byte[]之间的转换代码

 

本文中byte[]的顺序依照“大端顺序”。这句话的意思是说对于整数0x11223344

byte[0]保存0x11。byte[1]保存0x22。byte[2]保存0x33,byte[3]保存0x44

 

採用这样的“大端顺序”,由byte[]转int,或由int转byte[]。这里面byte的顺序都须要是上面描写叙述的“大端顺序”,这样优点是server发送时能够调用htonl。htons等函数将字节顺序转换为网络字节顺序,事实上关键是server和client要有一个一致的表示规范,看起来似乎网络字节顺序更顺眼一些?

 

Java对于各种基本类型的长度做了规定,所以相应byte数组的长度也固定,和机器无关。


以下是char,short,int,float,long,double转换的代码。核心是利用位操作,取出某个字节中的8个位,进行转换。

非常大程度上參考了http://tjmljw.iteye.com/blog/1767716一文中的实现(该文採用的是“小端顺序”的byte数组,我用的是“大端顺序”)。


import java.nio.ByteOrder;

public class ByteArrayConveter {

	// char转换为byte[2]数组
	public static byte[] getByteArray(char c) {
		byte[] b = new byte[2];
		b[0] = (byte) ((c & 0xff00) >> 8);
		b[1] = (byte) (c & 0x00ff);
		return b;
	}

	// 从byte数组的index处的连续两个字节获得一个char
	public static char getChar(byte[] arr, int index) {
		return (char) (0xff00 & arr[index] << 8 | (0xff & arr[index + 1]));
	}
	// short转换为byte[2]数组
	public static byte[] getByteArray(short s) {
		byte[] b = new byte[2];
		b[0] = (byte) ((s & 0xff00) >> 8);
		b[1] = (byte) (s & 0x00ff);
		return b;
	}
	// 从byte数组的index处的连续两个字节获得一个short
	public static short getShort(byte[] arr, int index) {
		return (short) (0xff00 & arr[index] << 8 | (0xff & arr[index + 1]));
	}
	// int转换为byte[4]数组
	public static byte[] getByteArray(int i) {
		byte[] b = new byte[4];
		b[0] = (byte) ((i & 0xff000000) >> 24);
		b[1] = (byte) ((i & 0x00ff0000) >> 16);
		b[2] = (byte) ((i & 0x0000ff00) >> 8);
		b[3] = (byte)  (i & 0x000000ff);
		return b;
	}
	// 从byte数组的index处的连续4个字节获得一个int
	public static int getInt(byte[] arr, int index) {
		return 	(0xff000000 	& (arr[index+0] << 24))  | 
				(0x00ff0000 	& (arr[index+1] << 16))  | 
				(0x0000ff00 	& (arr[index+2] << 8))   | 
				(0x000000ff 	&  arr[index+3]);
	}
	// float转换为byte[4]数组
	public static byte[] getByteArray(float f) {
		int intbits = Float.floatToIntBits(f);//将float里面的二进制串解释为int整数
		return getByteArray(intbits);
	}
	// 从byte数组的index处的连续4个字节获得一个float
	public static float getFloat(byte[] arr, int index) {
		return Float.intBitsToFloat(getInt(arr, index));
	}
	// long转换为byte[8]数组
	public static byte[] getByteArray(long l) {
		byte b[] = new byte[8];
		b[0] = (byte)  (0xff & (l >> 56));
		b[1] = (byte)  (0xff & (l >> 48));
		b[2] = (byte)  (0xff & (l >> 40));
		b[3] = (byte)  (0xff & (l >> 32));
		b[4] = (byte)  (0xff & (l >> 24));
		b[5] = (byte)  (0xff & (l >> 16));
		b[6] = (byte)  (0xff & (l >> 8));
		b[7] = (byte)  (0xff & l);
		return b;
	}
	// 从byte数组的index处的连续8个字节获得一个long
	public static long getLong(byte[] arr, int index) {
		return 	(0xff00000000000000L 	& ((long)arr[index+0] << 56))  | 
				(0x00ff000000000000L 	& ((long)arr[index+1] << 48))  | 
				(0x0000ff0000000000L 	& ((long)arr[index+2] << 40))  | 
				(0x000000ff00000000L 	& ((long)arr[index+3] << 32))  |
				(0x00000000ff000000L 	& ((long)arr[index+4] << 24))  | 
				(0x0000000000ff0000L 	& ((long)arr[index+5] << 16))  | 
				(0x000000000000ff00L 	& ((long)arr[index+6] << 8))   | 
				(0x00000000000000ffL 	&  (long)arr[index+7]);
	}
	// double转换为byte[8]数组
	public static byte[] getByteArray(double d) {
		long longbits = Double.doubleToLongBits(d);
		return getByteArray(longbits);
	}
	// 从byte数组的index处的连续8个字节获得一个double
	public static double getDouble(byte[] arr, int index) {
		return Double.longBitsToDouble(getLong(arr, index));
	}

	public static void main(String[] args) {
		System.out.println(ByteOrder.nativeOrder());
		if(args.length < 1){
			System.out.println("enter 'char' test method about char");
			System.out.println("enter 'short' test method about short");
			System.out.println("enter 'int' test method about int");
			System.out.println("enter 'float' test method about float");
			System.out.println("enter 'long' test method about long");
			System.out.println("enter 'double' test method about double");
			return;
		}
		if(args[0].equals("char")){
			char c = '\u0000';
			while( c < '\uffff'){
				System.out.println(getChar(getByteArray(c),0));
				c++;
			}
		}else if(args[0].equals("short")){
			short s = Short.MIN_VALUE;
			while( s < Short.MAX_VALUE){
				System.out.println(getShort(getByteArray(s), 0));
				s++;
			}
		}else if(args[0].equals("int")){
			int i = Integer.MIN_VALUE;
			while( i < Integer.MAX_VALUE){
				System.out.println(getInt(getByteArray(i), 0));
				i++;
			}
		}else if(args[0].equals("float")){
			float f = Float.MIN_VALUE;
			while(f < Float.MAX_VALUE){
				System.out.println(getFloat(getByteArray(f), 0));
				f+=1.1111f;
			}
		}else if(args[0].equals("long")){
			long l = Long.MIN_VALUE;
			while(l < Long.MAX_VALUE){
				System.out.println(getLong(getByteArray(l), 0));
				l++;
			}
		}else if(args[0].equals("double")){
			double d = Double.MIN_VALUE;
			while(d < Double.MAX_VALUE){
				System.out.println(getDouble(getByteArray(d), 0));
				d+=1.111D;
			}
		}
	}
}

说明:

本文由giantpoplar发表于CSDN

文章地址 http://write.blog.csdn.net/postedit/47657333

转载请保留本说明


posted on 2017-07-05 08:07  lxjshuju  阅读(8123)  评论(0编辑  收藏  举报