C# java 有关“字节序”的描述 .
有關(guān)“字節(jié)序”的描述?收藏
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型,而對(duì)單字節(jié)數(shù)據(jù)byte卻沒(méi)有影 響。BIG-ENDIAN就是低位字節(jié)排放在內(nèi)存的低端,高位字節(jié)排放在內(nèi)存的高端。而LITTLE-ENDIAN正好相反。?
比如 int a = 0x05060708?
在BIG-ENDIAN的情況下存放為:?
字節(jié)號(hào) 0 1 2 3?
數(shù)據(jù) 05 06 07 08?
在LITTLE-ENDIAN的情況下存放為:?
字節(jié)號(hào) 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ò)上傳輸時(shí)是大頭還是小頭的,在Internet的網(wǎng)絡(luò)字 節(jié)序是BIG-ENDIAN。所謂的JAVA字節(jié)序指的是在JAVA虛擬機(jī)中多字節(jié)類型數(shù)據(jù)的存放順序,JAVA字節(jié)序也是BIG-ENDIAN。?
3.所以在用C/C++寫(xiě)通信程序時(shí),在發(fā)送數(shù)據(jù)前務(wù)必用htonl和htons去把整型和短整型的數(shù)據(jù)進(jìn)行從主機(jī)字節(jié)序到網(wǎng)絡(luò)字節(jié)序的轉(zhuǎn)換,而接收數(shù)據(jù) 后對(duì)于整型和短整型數(shù)據(jù)則必須調(diào)用ntohl和ntohs實(shí)現(xiàn)從網(wǎng)絡(luò)字節(jié)序到主機(jī)字節(jié)序的轉(zhuǎn)換。如果通信的一方是JAVA程序、一方是C/C++程序時(shí), 則需要在C/C++一側(cè)使用以上幾個(gè)方法進(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ò)序,接收時(shí)反變換)。如果通信的雙方都是JAVA,則根本不用考慮字節(jié)序的問(wèn) 題了。?
4.如果網(wǎng)絡(luò)上全部是PowerPC,SPARC和Motorola CPU的主機(jī)那么不會(huì)出現(xiàn)任何問(wèn)題,但由于實(shí)際存在大量的IA架構(gòu)的CPU,所以經(jīng)常出現(xiàn)數(shù)據(jù)傳輸錯(cuò)誤。?
5.文章開(kāi)頭所提出的問(wèn)題,就是因?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ù)解釋自然出錯(cuò)。?
具體數(shù)據(jù)如下,實(shí)際發(fā)送的數(shù)據(jù)為23578?
發(fā)送端發(fā)送數(shù)據(jù): 1A 5C?
接收端接收到數(shù)據(jù)后,按BIG-ENDIAN進(jìn)行解釋具體數(shù)據(jù)是多少?你們自己去計(jì)算并比較吧!
===============================================================================================
? ? 談到字節(jié)序的問(wèn)題,必然牽涉到兩大CPU派系。那就是Motorola的PowerPC系列CPU和Intel的x86系列CPU。PowerPC系列采 用big endian方式存儲(chǔ)數(shù)據(jù),而x86系列則采用little endian方式存儲(chǔ)數(shù)據(jù)。那么究竟什么是big endian,什么又是little endian呢??
? ? 其實(shí)big endian是指低地址存放最高有效字節(jié)(MSB),而little endian則是低地址存放最低有效字節(jié)(LSB),即常說(shuō)的低位在先,高位在后。?
? ? 用文字說(shuō)明可能比較抽象,下面用圖像加以說(shuō)明。比如數(shù)字0x12345678在兩種不同字節(jié)序CPU中的存儲(chǔ)順序如下所示:?
Big Endian?
? 低地址 ? ? ? ? ? ? ? ? ? ? ? ? ? 高地址?
? ----------------------------------------->?
? +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+?
? | ? ? 12 ? ? | ? ? ?34 ? ?| ? ? 56 ? ? ?| ? ? 78 ? ?|?
? +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+?
Little Endian?
? 低地址 ? ? ? ? ? ? ? ? ? ? ? ? ? 高地址?
? ----------------------------------------->?
? +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+?
? | ? ? 78 ? ? | ? ? ?56 ? ?| ? ? 34 ? ? ?| ? ? 12 ? ?|?
? +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+?
? ? 從上面兩圖可以看出,采用big endian方式存儲(chǔ)數(shù)據(jù)是符合我們?nèi)祟惖乃季S習(xí)慣的。而little endian,!@#$%^&*,見(jiàn)鬼去吧 -_-|||?
? ? 為什么要注意字節(jié)序的問(wèn)題呢?你可能這么問(wèn)。當(dāng)然,如果你寫(xiě)的程序只在單機(jī)環(huán)境下面運(yùn)行,并且不和別人的程序打交道,那么你完全可以忽略字節(jié)序的存在。但 是,如果你的程序要跟別人的程序產(chǎn)生交互呢?尤其是當(dāng)你把你在微機(jī)上運(yùn)算的結(jié)果運(yùn)用到計(jì)算機(jī)群上去的話。在這里我想說(shuō)說(shuō)兩種語(yǔ)言。C/C++語(yǔ)言編寫(xiě)的程 序里數(shù)據(jù)存儲(chǔ)順序是跟編譯平臺(tái)所在的CPU相關(guān)的,而JAVA編寫(xiě)的程序則唯一采用big endian方式來(lái)存儲(chǔ)數(shù)據(jù)。試想,如果你用C/C++語(yǔ)言在x86平臺(tái)下編寫(xiě)的程序跟別人的JAVA程序互通時(shí)會(huì)產(chǎn)生什么結(jié)果?就拿上面的 0x12345678來(lái)說(shuō),你的程序傳遞給別人的一個(gè)數(shù)據(jù),將指向0x12345678的指針傳給了JAVA程序,由于JAVA采取big endian方式存儲(chǔ)數(shù)據(jù),很自然的它會(huì)將你的數(shù)據(jù)翻譯為0x78563412。什么?竟然變成另外一個(gè)數(shù)字了?是的,就是這種后果。因此,在你的C程序 傳給JAVA程序之前有必要進(jìn)行字節(jié)序的轉(zhuǎn)換工作。?
? ? 無(wú)獨(dú)有偶,所有網(wǎng)絡(luò)協(xié)議也都是采用big endian的方式來(lái)傳輸數(shù)據(jù)的。所以有時(shí)我們也會(huì)把big endian方式稱之為網(wǎng)絡(luò)字節(jié)序。當(dāng)兩臺(tái)采用不同字節(jié)序的主機(jī)通信時(shí),在發(fā)送數(shù)據(jù)之前都必須經(jīng)過(guò)字節(jié)序的轉(zhuǎn)換成為網(wǎng)絡(luò)字節(jié)序后再進(jìn)行傳輸。ANSI C中提供了四個(gè)轉(zhuǎn)換字節(jié)序的宏。
--------------------------------------------------------------------------------
/** * 通信格式轉(zhuǎn)換 * * Java和一些windows編程語(yǔ)言如c、c++、delphi所寫(xiě)的網(wǎng)絡(luò)程序進(jìn)行通訊時(shí),需要進(jìn)行相應(yīng)的轉(zhuǎn)換 * 高、低字節(jié)之間的轉(zhuǎn)換 * windows的字節(jié)序?yàn)榈妥止?jié)開(kāi)頭 * linux,unix的字節(jié)序?yàn)楦咦止?jié)開(kāi)頭 * java則無(wú)論平臺(tái)變化,都是高字節(jié)開(kāi)頭 */ 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< 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
轉(zhuǎn)載于:https://www.cnblogs.com/vhtt/archive/2009/10/10/1580335.html
總結(jié)
以上是生活随笔為你收集整理的C# java 有关“字节序”的描述 .的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 数字与企鹅的战争,看周红衣的高明之处
- 下一篇: fluorinefx C# 版的开源rt