Java?int類型如何獲取高低位
int類型如何獲取高低位
去年筆者和一個硬件廠商調(diào)試打印機的時候遇到這個一個問題,廠商需要打印報文中傳輸報文的長度標志,按大端序,將長度的高位和低位放到兩個字節(jié)里,筆者由于基礎知識不牢固,在這個問題上浪費了較長時間,今年開始寫博客了,就記錄一下這個問題。筆者使用了int來記錄長度,其實應該用兩個字節(jié)的short來記錄,這樣更簡單。
大小端序
要想拿int的高低位字節(jié),首先要理解大小端序。這里以int舉例,int有四個字節(jié)A,B,C,D。那么內(nèi)存里存儲int類型占用了四個字節(jié)的位置,這四個字節(jié)在內(nèi)存中肯定占用了連續(xù)遞增的四個地址,大小端序指得就是這四個字節(jié)在這四個地址中是順序排列的還是逆序排列的。如果是順序排列的,那么我們叫大端序,如果是逆序排列的,就叫小端序。
再拿網(wǎng)絡傳輸這個int值來舉例,甲向乙傳輸數(shù)據(jù),乙拿到甲傳的字節(jié)數(shù)組以后要知道怎么拼接這四個字節(jié),如果甲是按順序傳輸這四個字節(jié),而乙按逆序拼接四個字節(jié),那么雙方得到的int值肯定是不一樣的。那么怎么解決這個問題呢?方法就是雙方協(xié)定一個順序,比如按大端序傳輸,甲將四個字節(jié)按大端序傳輸給乙,乙再按大端序拼接字節(jié),這樣雙方得到的int值就是一樣的了。
總結一下就是,大端序,高位字節(jié)在前,低位字節(jié)在后。小端序,高位字節(jié)在后,低位字節(jié)在前。一般交互都是默認大端序。
獲取int的高低位字節(jié)數(shù)組
這里給出了大小端序的int和字節(jié)數(shù)組互轉函數(shù)
/**
* 小端序 字節(jié)數(shù)組轉int
*
* @param bytes
* @return
*/
public static int littleEndian(byte[] bytes) {
return (bytes[0]&0XFF)
| ((bytes[1]&0XFF) << 8)
| ((bytes[2]&0XFF) << 16)
| ((bytes[3]&0XFF) << 24);
}
/**
* 大端序 字節(jié)數(shù)組轉int
*
* @param bytes
* @return
*/
public static int bigEndian(byte[] bytes) {
//System.out.println(String.format("%32s", Integer.toBinaryString(bytes[3]&0XFF)).replaceAll("\\s", "0"));
//System.out.println(String.format("%32s", Integer.toBinaryString(((bytes[2]&0XFF) << 8)).replaceAll("\\s", "0")));
//System.out.println(String.format("%32s", Integer.toBinaryString(((bytes[1]&0XFF) << 16)).replaceAll("\\s", "0")));
//System.out.println(String.format("%32s", Integer.toBinaryString(((bytes[0]&0XFF) << 24)).replaceAll("\\s", "0")));
return (bytes[3]&0XFF)
| ((bytes[2]&0XFF) << 8)
| ((bytes[1]&0XFF) << 16)
| ((bytes[0]&0XFF) << 24);
}
/**
* 大端序 int轉字節(jié)數(shù)組
*
* @param i
* @return
*/
public static byte[] bigEndian(int i) {
int byte1 = i & 0XFF;
int byte2 = (i & 0XFFFF) >>> 8;
int byte3 = (i & 0XFFFFFF) >>> 16;
int byte4 = (i & 0XFFFFFFFF) >>> 24;
return new byte[]{(byte) byte4, (byte) byte3, (byte) byte2, (byte) byte1};
}
/**
* 小端序 int轉字節(jié)數(shù)組
*
* @param i
* @return
*/
public static byte[] littleEndian(int i) {
int byte1 = i & 0XFF;
int byte2 = (i & 0XFF << 8) >> 8;
int byte3 = (i & 0XFF << 16) >> 16;
int byte4 = (i & 0XFF << 24) >> 24;
return new byte[]{(byte) byte1, (byte) byte2, (byte) byte3, (byte) byte4};
}
public static void main(String[] args) {
int a = new Random().nextInt();
String s = String.format("%32s", Integer.toBinaryString(a)).replaceAll("\\s", "0");
System.out.println("原數(shù)據(jù): " + s.substring(0, 8) + " " + s.substring(8, 16) + " " + s.substring(16, 24) + " " + s.substring(24, 32) + " ");
byte[] bytes = bigEndian(a);
System.out.printf("大端序-int轉字節(jié)數(shù)組:");
for (int i = 0; i < bytes.length; i++) {
System.out.print(String.format("%8s", Integer.toBinaryString(bytes[i] & 0XFF)).replaceAll("\\s", "0") + " ");
}
System.out.println();
System.out.println("大端序-字節(jié)數(shù)組轉int驗證:" + (bigEndian(bytes) == a));
byte[] bytes2 = littleEndian(a);
System.out.printf("小端序-int轉字節(jié)數(shù)組:");
for (int i = 0; i < bytes2.length; i++) {
System.out.print(String.format("%8s", Integer.toBinaryString(bytes2[i] & 0XFF)).replaceAll("\\s", "0") + " ");
}
System.out.println();
System.out.println("小端序-字節(jié)數(shù)組轉int驗證:" + (littleEndian(bytes2) == a));
}
}
原數(shù)據(jù): 10010100 11111001 01101110 00100011
大端序-int轉字節(jié)數(shù)組:10010100 11111001 01101110 00100011
大端序-字節(jié)數(shù)組轉int驗證:true
小端序-int轉字節(jié)數(shù)組:00100011 01101110 11111001 10010100
小端序-字節(jié)數(shù)組轉int驗證:true高低位和byte轉int
最近研究I/O流,發(fā)現(xiàn)read()方法返回的是int類型,原來是將一個byte讀入到一個int,有效的數(shù)據(jù)只占據(jù)int型變量的最低8位。在正常情況下這個int型的變量永遠都不可能是負數(shù)。
什么是高低位?
一個Byte是8位(bit),其中的“8位”指的是8位2進制數(shù)。byte范圍是-128--127,如果輸入超過這個數(shù)值,會編譯錯誤。
如8位二進制數(shù):11001010;1100就是高4位,后面的1010就是低4位。
什么是低8位?
一個int類型的變量能存放4Byte,也就是能存放32位二進制數(shù),而一個32位二進制數(shù)中權值最大的24位就是高24位,那么剩下的就是低8位。
如何將byte轉換為int?
需要將前24位去除,也就是轉換為0。Java對byte總是做有符號處理;
所以可以通過將byte和0xff進行二進制“&“得到它的無符值。
例如:
byte的二進制為:11001010;
0xff的二進制為:11111111;
1111111111111111111111111 11001010 & 11111111 = 000000000000000000000000 11001010
上面的例子為什么會添加這么多“1”?
當系統(tǒng)檢測到byte可能會轉化成int或者說byte與int類型進行運算的時候,就會將byte的內(nèi)存空間高位補1(也就是按符號位補位)擴充到32位
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Java中的NoSuchMethodException異常原因以及解決方案詳解
這篇文章主要介紹了Java中的NoSuchMethodException異常原因以及解決方案詳解,NoSuchMethodException是Java反射機制中的異常,在嘗試通過反射獲取方法時,找不到指定的方法,通常發(fā)生在調(diào)用?Class?對象的方法時,當方法名或方法參數(shù)不匹配時拋出該異常,需要的朋友可以參考下2024-02-02
Spring定時任務關于@EnableScheduling的用法解析
這篇文章主要介紹了Spring定時任務關于@EnableScheduling的用法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06
java URL 獲取PHP JSON 數(shù)據(jù)
這篇文章主要介紹了java URL 獲取PHP JSON 數(shù)據(jù),需要的朋友可以參考下2016-04-04
sftp和ftp 根據(jù)配置遠程服務器地址下載文件到當前服務
這篇文章主要介紹了sftp和ftp 根據(jù)配置遠程服務器地址下載文件到當前服務的相關資料本文給大家介紹的非常詳細,具有參考借鑒價值,需要的朋友可以參考下2016-10-10

