<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    byterat

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      54 隨筆 :: 0 文章 :: 15 評論 :: 0 Trackbacks

    BIG-ENDIAN(大字節(jié)序、高字節(jié)序)
    LITTLE-ENDIAN(小字節(jié)序、低字節(jié)序)
    主機(jī)字節(jié)序
    網(wǎng)絡(luò)字節(jié)順序
    JAVA字節(jié)序

    1.BIG-ENDIAN、LITTLE-ENDIAN跟多字節(jié)類型的數(shù)據(jù)有關(guān)的比如int,short,long型,而對單字節(jié)數(shù)據(jù)byte卻沒有影響。BIG-ENDIAN就是低位字節(jié)排放在內(nèi)存的低端,高位字節(jié)排放在內(nèi)存的高端。而LITTLE-ENDIAN正好相反。
    比如 int a = 0x05060708
    在BIG-ENDIAN的情況下存放為:
    字節(jié)號 0 1 2 3
    數(shù)據(jù) 05 06 07 08
    在LITTLE-ENDIAN的情況下存放為:
    字節(jié)號 0 1 2 3
    數(shù)據(jù) 08 07 06 05

    2.BIG-ENDIAN、LITTLE-ENDIAN、跟CPU有關(guān)的,每一種CPU不是BIG-ENDIAN就是LITTLE-ENDIAN、。IA架構(gòu)的CPU中是Little-Endian,而PowerPC 、SPARC和Motorola處理器。這其實(shí)就是所謂的主機(jī)字節(jié)序。而網(wǎng)絡(luò)字節(jié)序是指數(shù)據(jù)在網(wǎng)絡(luò)上傳輸時是大頭還是小頭的,在Internet的網(wǎng)絡(luò)字節(jié)序是BIG-ENDIAN。所謂的JAVA字節(jié)序指的是在JAVA虛擬機(jī)中多字節(jié)類型數(shù)據(jù)的存放順序,JAVA字節(jié)序也是BIG-ENDIAN。

    3.所以在用C/C++寫通信程序時,在發(fā)送數(shù)據(jù)前務(wù)必用htonl和htons去把整型和短整型的數(shù)據(jù)進(jìn)行從主機(jī)字節(jié)序到網(wǎng)絡(luò)字節(jié)序的轉(zhuǎn)換,而接收數(shù)據(jù)后對于整型和短整型數(shù)據(jù)則必須調(diào)用ntohl和ntohs實(shí)現(xiàn)從網(wǎng)絡(luò)字節(jié)序到主機(jī)字節(jié)序的轉(zhuǎn)換。如果通信的一方是JAVA程序、一方是C/C++程序時,則需要在C/C++一側(cè)使用以上幾個方法進(jìn)行字節(jié)序的轉(zhuǎn)換,而JAVA一側(cè),則不需要做任何處理,因?yàn)镴AVA字節(jié)序與網(wǎng)絡(luò)字節(jié)序都是BIG-ENDIAN,只要C/C++一側(cè)能正確進(jìn)行轉(zhuǎn)換即可(發(fā)送前從主機(jī)序到網(wǎng)絡(luò)序,接收時反變換)。如果通信的雙方都是JAVA,則根本不用考慮字節(jié)序的問題了。

    4.如果網(wǎng)絡(luò)上全部是PowerPC,SPARC和Motorola CPU的主機(jī)那么不會出現(xiàn)任何問題,但由于實(shí)際存在大量的IA架構(gòu)的CPU,所以經(jīng)常出現(xiàn)數(shù)據(jù)傳輸錯誤。

    5.文章開頭所提出的問題,就是因?yàn)槌绦蜻\(yùn)行在X86架構(gòu)的PC SERVER上,發(fā)送數(shù)據(jù)的一端用C實(shí)現(xiàn)的,接收一端是用JAVA實(shí)現(xiàn)的,而發(fā)送端在發(fā)送數(shù)據(jù)前未進(jìn)行從主機(jī)字節(jié)序到網(wǎng)絡(luò)字節(jié)序的轉(zhuǎn)換,這樣接收端接收到的是LITTLE-ENDIAN的數(shù)據(jù),數(shù)據(jù)解釋自然出錯。
    具體數(shù)據(jù)如下,實(shí)際發(fā)送的數(shù)據(jù)為23578
    發(fā)送端發(fā)送數(shù)據(jù): 1A 5C
    接收端接收到數(shù)據(jù)后,按BIG-ENDIAN進(jìn)行解釋具體數(shù)據(jù)是多少?你們自己去計(jì)算并比較吧!


    ===============================================================================================

    Big Endian and Little Endian

        談到字節(jié)序的問題,必然牽涉到兩大CPU派系。那就是Motorola的PowerPC系列CPU和Intel的x86系列CPU。PowerPC系列采用big endian方式存儲數(shù)據(jù),而x86系列則采用little endian方式存儲數(shù)據(jù)。那么究竟什么是big endian,什么又是little endian呢?

        其實(shí)big endian是指低地址存放最高有效字節(jié)(MSB),而little endian則是低地址存放最低有效字節(jié)(LSB),即常說的低位在先,高位在后。
        用文字說明可能比較抽象,下面用圖像加以說明。比如數(shù)字0x12345678在兩種不同字節(jié)序CPU中的存儲順序如下所示:

    Big Endian

      低地址                           高地址
      ----------------------------------------->
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |     12     |      34    |     56      |     78    |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    Little Endian

      低地址                           高地址
      ----------------------------------------->
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |     78     |      56    |     34      |     12    |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

        從上面兩圖可以看出,采用big endian方式存儲數(shù)據(jù)是符合我們?nèi)祟惖乃季S習(xí)慣的。而little endian,!@#$%^&*,見鬼去吧 -_-|||

        為什么要注意字節(jié)序的問題呢?你可能這么問。當(dāng)然,如果你寫的程序只在單機(jī)環(huán)境下面運(yùn)行,并且不和別人的程序打交道,那么你完全可以忽略字節(jié)序的存在。但是,如果你的程序要跟別人的程序產(chǎn)生交互呢?尤其是當(dāng)你把你在微機(jī)上運(yùn)算的結(jié)果運(yùn)用到計(jì)算機(jī)群上去的話。在這里我想說說兩種語言。C/C++語言編寫的程序里數(shù)據(jù)存儲順序是跟編譯平臺所在的CPU相關(guān)的,而JAVA編寫的程序則唯一采用big endian方式來存儲數(shù)據(jù)。試想,如果你用C/C++語言在x86平臺下編寫的程序跟別人的JAVA程序互通時會產(chǎn)生什么結(jié)果?就拿上面的 0x12345678來說,你的程序傳遞給別人的一個數(shù)據(jù),將指向0x12345678的指針傳給了JAVA程序,由于JAVA采取big endian方式存儲數(shù)據(jù),很自然的它會將你的數(shù)據(jù)翻譯為0x78563412。什么?竟然變成另外一個數(shù)字了?是的,就是這種后果。因此,在你的C程序傳給JAVA程序之前有必要進(jìn)行字節(jié)序的轉(zhuǎn)換工作。

        無獨(dú)有偶,所有網(wǎng)絡(luò)協(xié)議也都是采用big endian的方式來傳輸數(shù)據(jù)的。所以有時我們也會把big endian方式稱之為網(wǎng)絡(luò)字節(jié)序。當(dāng)兩臺采用不同字節(jié)序的主機(jī)通信時,在發(fā)送數(shù)據(jù)之前都必須經(jīng)過字節(jié)序的轉(zhuǎn)換成為網(wǎng)絡(luò)字節(jié)序后再進(jìn)行傳輸。ANSI C中提供了四個轉(zhuǎn)換字節(jié)序的宏。


    ========================================================================================================

    /**
    * 通信格式轉(zhuǎn)換
    *
    * Java和一些windows編程語言如c、c++、delphi所寫的網(wǎng)絡(luò)程序進(jìn)行通訊時,需要進(jìn)行相應(yīng)的轉(zhuǎn)換
    * 高、低字節(jié)之間的轉(zhuǎn)換
    * windows的字節(jié)序?yàn)榈妥止?jié)開頭
    * linux,unix的字節(jié)序?yàn)楦咦止?jié)開頭
    * java則無論平臺變化,都是高字節(jié)開頭
    */

    public class FormatTransfer {
    /**
      * 將int轉(zhuǎn)為低字節(jié)在前,高字節(jié)在后的byte數(shù)組
      * @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轉(zhuǎn)為高字節(jié)在前,低字節(jié)在后的byte數(shù)組
      * @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轉(zhuǎn)為低字節(jié)在前,高字節(jié)在后的byte數(shù)組
      * @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轉(zhuǎn)為高字節(jié)在前,低字節(jié)在后的byte數(shù)組
      * @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轉(zhuǎn)為高字節(jié)在前,低字節(jié)在后的byte數(shù)組

    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轉(zhuǎn)為低字節(jié)在前,高字節(jié)在后的byte數(shù)組
      */
    public static byte[] toLH(float f) {
      return toLH(Float.floatToRawIntBits(f));
    }

    /**
      * 將float轉(zhuǎn)為高字節(jié)在前,低字節(jié)在后的byte數(shù)組
      */
    public static byte[] toHH(float f) {
      return toHH(Float.floatToRawIntBits(f));
    }

    /**
      * 將String轉(zhuǎn)為byte數(shù)組
      */
    public static byte[] stringToBytes(String s, int length) {
      while (s.getBytes().length < length) {
        s += " ";
      }
      return s.getBytes();
    }


    /**
      * 將字節(jié)數(shù)組轉(zhuǎn)換為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 & 0xff));
      }
      return result.toString();
    }

    /**
      * 將字符串轉(zhuǎn)換為byte數(shù)組
      * @param s String
      * @return byte[]
      */
    public static byte[] stringToBytes(String s) {
      return s.getBytes();
    }

    /**
      * 將高字節(jié)數(shù)組轉(zhuǎn)換為int
      * @param b byte[]
      * @return int
      */
    public static int hBytesToInt(byte[] b) {
      int s = 0;
      for (int i = 0; i < 3; i++) {
        if (b >= 0) {
        s = s + b;
        } else {
        s = s + 256 + b;
        }
        s = s * 256;
      }
      if (b[3] >= 0) {
        s = s + b[3];
      } else {
        s = s + 256 + b[3];
      }
      return s;
    }

    /**
      * 將低字節(jié)數(shù)組轉(zhuǎn)換為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;
    }


    /**
      * 高字節(jié)數(shù)組到short的轉(zhuǎn)換
      * @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;
    }

    /**
      * 低字節(jié)數(shù)組到short的轉(zhuǎn)換
      * @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;
    }

    /**
      * 高字節(jié)數(shù)組轉(zhuǎn)換為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);
    }

    /**
      * 低字節(jié)數(shù)組轉(zhuǎn)換為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數(shù)組中的元素倒序排列
      */
    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;
      }
      return result;
    }

    /**
      * 打印byte數(shù)組
      */
    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 ut = "";
      for (int i=0; i<length; i++) {
        ut = out + bb + " ";
      }

    }

    /**
      * 將int類型的值轉(zhuǎn)換為字節(jié)序顛倒過來對應(yīng)的int值
      * @param i int
      * @return int
      */
    public static int reverseInt(int i) {
      int result = FormatTransfer.hBytesToInt(FormatTransfer.toLH(i));
      return result;
    }

    /**
      * 將short類型的值轉(zhuǎn)換為字節(jié)序顛倒過來對應(yīng)的short值
      * @param s short
      * @return short
      */
    public static short reverseShort(short s) {
      short result = FormatTransfer.hBytesToShort(FormatTransfer.toLH(s));
      return result;
    }

    /**
      * 將float類型的值轉(zhuǎn)換為字節(jié)序顛倒過來對應(yīng)的float值
      * @param f float
      * @return float
      */
    public static float reverseFloat(float f) {
      float result = FormatTransfer.hBytesToFloat(FormatTransfer.toLH(f));
      return result;
    }

    }

    posted on 2007-10-24 09:57 比特鼠 閱讀(3406) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 国产成人免费在线| 日韩精品无码免费专区网站| 可以免费看的卡一卡二| 亚洲一区无码中文字幕乱码| 亚洲黄色片免费看| 亚洲一区在线观看视频| 在线观看免费人成视频色9| 亚洲一区欧洲一区| 日本牲交大片免费观看| 黄网站色成年片大免费高清| 亚洲欧洲中文日韩av乱码| 中文字幕av免费专区| 亚洲国产精品福利片在线观看| 久久久久久成人毛片免费看| 久久综合亚洲色一区二区三区| AV无码免费永久在线观看| 亚洲愉拍一区二区三区| 免费人成视网站在线观看不卡| 久久国产一片免费观看| 一区二区三区亚洲| 一二三四视频在线观看中文版免费| 国产人成亚洲第一网站在线播放| 全部免费a级毛片| 久久国产免费观看精品| 亚洲偷自精品三十六区| 亚洲国产高清精品线久久| 久久精品国产免费| 亚洲性色精品一区二区在线| 亚洲国产成人影院播放| 久久九九兔免费精品6| 亚洲另类无码一区二区三区| 亚洲黄黄黄网站在线观看| 99久热只有精品视频免费观看17| 亚洲精品自偷自拍无码| 亚洲日韩精品一区二区三区| 丁香花在线观看免费观看| 七次郎成人免费线路视频| 亚洲短视频在线观看| 亚洲色偷偷狠狠综合网| 中文字幕乱码免费视频| 国产精品永久免费|