java byte陣列異或校驗時出現負數問題
阿新 • • 發佈:2018-12-15
簡介
最近由於需要對接校園的刷卡機支付,協議需要用到異或校驗。參照校驗的流程對相鄰陣列進行異或,得出的結果卻與示例的不一樣,而且還是負數。
起先以為自己的演算法或者資料有問題,但是檢查了一遍後還是一樣。
分析原因
由於協議中有欄位表示的數值大於127,如協議中該欄位16進製為0XA2,本來數值應該是162,結果轉變成byte時變成了-94,異或校驗後該欄位的數值變為了負數,導致異或校驗的結果不正確,這是因為java中的byte是有符號位的byte,這點和c++不一樣,因此可表示的資料為-127~127(最高位為符號位)。知道了原因,剩下的就是問題的解決了。
解決方法
既然是數值太大導致byte溢位了,那麼只要解決溢位的問題就好了。在這裡我們只關心校驗的結果,因此把byte用int型別來表示就能解決數值的問題了。
可以將異或的結果使用int型別表示(這是為了防止結果出現負數),在異或的過程中,將溢位的byte資料(即數值超出127的)通過&0xff將符號為變成正數,同時由於byte儲存不了變為正數的資料,需要分配一個臨時變數來儲存並參與運算。
以下為解決的程式碼:
/** 獲取指令異或值
* @param datas
* @return
*/
private int getXOR(byte[] datas) {
int temp = datas[1]; // 此處首位取1是因為本協議中第一個資料不引數異或校驗,轉為int防止結果出現溢位變成負數
for (int i = 2; i < datas.length; i++) {
int preTemp = temp;
int iData;
if (datas[i] < 0) {
iData = datas[i] & 0xff; // 變為正數計算
} else {
iData = datas[i];
}
if (temp < 0) {
temp = temp & 0xff; // 變為正數
}
temp ^= iData;
System.out.println(preTemp + "異或" + iData + "=" + temp);
}
return temp;
}