java socket tcp/ip基本資料型別編解碼【高序位元組 低序位元組】
package com.learning.forsocket.decodeencode;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
/*
* 一下程式碼是根據java socket tcp/ip程式設計書籍中對基本型別編碼例子新增相關自己註釋以及理解
*
*因主機CPU不同,不同的機器會出現高、低兩種位元組序問題
*Little endian:將低序位元組儲存在起始地址
*Big endian:將高序位元組儲存在起始地址
* JAVA是網路位元組序 位元組儲存高位元組序
*java中提供相應的方法 也可以通過移位來實現【列子中是高位元組位儲存例子可以通過修改順序實現Little endian】
*
*/
public class BruteForceCoding {
private static byte byteVal = 101;
private static short shortVal = 10001;
private static int intVal = 100000001;
private static long longVal = 1000000000001L;
/** * byte short int long 型別佔用幾個位元組 * */ private final static int BSIZE = Byte.BYTES; private final static int SSIZE = Short.BYTES; private final static int ISIZE = Integer.BYTES; private final static int LSIZE = Long.BYTES; /******* * 定義整數進行將無符號轉成有符號的資料進行擴充套件位使用【主要針對一個位元組來輸出資料,方便觀察資料】 * */ private final static int BYTEMASK = 0xFF; /*** * 此方法的是將一個位元組資料的資料以無符號十進位制資料展示,主要方便我們觀察儲存資料 * * **/ public static String byteArrayToDecimalString(byte[] bArray) { StringBuilder rtn=new StringBuilder(); for (byte b : bArray) { rtn.append(b&BYTEMASK).append(" "); /*** * 這塊的邏輯【有符號轉負】:比如-128的資料【補碼】 10000000--》-128的擴充套件為是11111111 11111111 11111111 10000000 與 00000000 00000000 * 00000000 11111111 做&運算 00000000 00000000 00000000 1000000--->即是128 -127-->對應129 * 也可以這樣簡單理解:1個位元組 -128-127 如果變成無符號的一個位元組大小就是0-255 由於資料資料是週期性127之後就是-128對應129 ...-1就是255 */ } return rtn.toString(); } /**** * * @param dst 位元組陣列 * @param val 資料 * @param offset 存的偏移量 * @param size 存放幾個位元組 * @return */ public static int encodeIntBigEndian(byte[]dst,long val,int offset,int size){ for (int i = 0; i < size; i++) { //位元組陣列先存高位然後地位位元組 dst[offset++]= (byte) (val>>((size-i-1)*Byte.SIZE)); } return offset;//返回的資料表示位元組資料的位置 } /** * * @param val 位元組資料 * @param offset 讀取的開始位元組陣列位置 * @param size 幾個位元組 * @return */ public static long decodeIntBigEndian(byte[] val,int offset,int size){ long rtn=0; for (int i = 0; i < size; i++) { /** *處理方式方式:第一次rtn=0,假設取兩個位元組 offset=1 * 首先去val[offset],第二個位元組,首先rtn左移動8位,然後取val[offset+1] 取最後8位 做|運算 * 其他的計算依然如此 */ rtn=(rtn<<Byte.SIZE)|((long)val[offset+i]&BYTEMASK); } return rtn; } /*** * 將有符號的位元組轉成int * @param data * @return */ public static int getUnsignedByte (byte data){ return data&0x0FF ; } public static void main(String[] args) throws Exception { //
// byte sortdata=-1;
// System.out.println(getUnsignedByte(sortdata));
//定義一個位元組資料 byte[] mesage=new byte[BSIZE+SSIZE+ISIZE+LSIZE];//1+2+4+8 15個位元組 //編碼 分別將 byte short int long型別的資料寫入位元組資料【超過1一個位元組的資料型別 高位在前 低位在後】 int offset=encodeIntBigEndian(mesage,byteVal,0,BSIZE); offset=encodeIntBigEndian(mesage,shortVal,offset,SSIZE); offset=encodeIntBigEndian(mesage,intVal,offset,ISIZE); offset=encodeIntBigEndian(mesage,longVal,offset,LSIZE); System.out.println("Encode message:"+byteArrayToDecimalString(mesage)); //解碼 long value=decodeIntBigEndian(mesage,0,BSIZE); System.out.println("Docoded byte="+value); value=decodeIntBigEndian(mesage,BSIZE,SSIZE);//從下標是1的位置開始讀取2個位元組 System.out.println("Docoded short="+value); value=decodeIntBigEndian(mesage,3,ISIZE);//從下標是1的位置開始讀取2個位元組 System.out.println("Docoded int="+value); value=decodeIntBigEndian(mesage,BSIZE+SSIZE+ISIZE,LSIZE);//從下標是7的位置開始讀取8個位元組 System.out.println("Docoded long="+value); offset=4; value=decodeIntBigEndian(mesage,offset,BSIZE);//表示取第五個位元組取一個位元組 245 System.out.println("Decoded value(offset "+offset+",size "+BSIZE+")="+value); byte bVal=(byte)decodeIntBigEndian(mesage,offset,BSIZE);//-11 System.out.println("Same value as byte="+bVal); /*java提供原聲方法進行輸出【高序位元組】*/ ByteArrayOutputStream buf=new ByteArrayOutputStream(); DataOutputStream out=new DataOutputStream(buf); out.writeByte(byteVal); out.writeShort(shortVal); out.writeInt(intVal); out.writeLong(longVal); out.flush(); byte[] msg=buf.toByteArray(); System.out.println("Encode message:"+byteArrayToDecimalString(msg)); }
}
===========================================================
Java提供的方法也是通過移位來實現的,debug跟進可以看到: