1. 程式人生 > >java socket tcp/ip基本資料型別編解碼【高序位元組 低序位元組】

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跟進可以看到:
這裡寫圖片描述這裡寫圖片描述