我試圖將十六進制轉換爲大整數。基本上我有32個字符= 16個字節,因此,我希望BigInteger
也有16個字節,但對於一些情況,即十六進制99開始..它以0我使用將十六進制轉換爲BigInteger
new BigInteger(hex, 16)
如何產生額外的字節我可以避開第17個字節嗎?
我試圖將十六進制轉換爲大整數。基本上我有32個字符= 16個字節,因此,我希望BigInteger
也有16個字節,但對於一些情況,即十六進制99開始..它以0我使用將十六進制轉換爲BigInteger
new BigInteger(hex, 16)
如何產生額外的字節我可以避開第17個字節嗎?
超過127字節的值不能與Java的byte
表示,因爲他們已登錄(當然,他們可以但Java將他們視爲負數)。
當BigInteger
將該值轉換爲字節數組時,它會在前面添加一個0字節以區分正值與負值。
這導致128
將變爲[0][-128]
,而-128
將變成[-128]
。
如果您打算將結果字節存儲爲一個無符號的128位值,那麼您可以截斷該數組的第一個元素,例如, byte[] sanitizedBytes = Arrays.copyOfRange(myBytes, 1, 16);
。
不可變的任意精度的整數。所有的操作都表現得好像BigInteger以2的補碼錶示法(例如Java的 原始整數類型)表示。
description of the constructor you are using和:
將BigInteger的指定 基數成一個BigInteger字符串表示。字符串表示由一個 可選的負號或加號組成,後跟一個或多個指定基數的 數字序列。字符到數字的映射是由Character.digit提供的 。該字符串不得包含任何無關的 字符(例如,空格)。
這意味着,如果你有new BigInteger("99000000000000000000000000000000", 16)
調用它,你會得到一個BigInteger,其中認爲值(爲正值),就好像它是在二進制補碼錶示法表示。二進制補碼中的正值不適合16字節,所以最終的結果當然是17字節長。
你保證,如果你與之間的值調用它來獲得一個BigInteger與16個字節的maximun(包括兩端):
- new BigInteger("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16)
- new BigInteger("-80000000000000000000000000000000", 16)
比第一次比一次更高或更低的任何值會導致超過16個字節。
第一個字節不能以1
位開始,因爲那意味着一個負數。他們通過在數組起始處添加額外的零字節來防止這種情況。該功能將檢查和砍掉那個字節:
public static byte[] signedToUnsignedBytes(byte[] myBytes) {
return myBytes.length > 1 && myBytes[0] == 0
? Arrays.copyOfRange(myBytes, 1, myBytes.length)
: myBytes;
}
看來你是使用BigInteger
的唯一目的,以固定長度的十六進制字符串轉換爲byte[]
陣列。使用Long.parseUnsignedLong()
在Java的8
static byte[] toByteArray(String s) {
ByteBuffer bb = ByteBuffer.allocate(16);
bb.asIntBuffer().put((int) Long.parseLong(s.substring(0, 8), 16))
.put((int) Long.parseLong(s.substring(8, 16), 16))
.put((int) Long.parseLong(s.substring(16, 24), 16))
.put((int) Long.parseLong(s.substring(24), 16));
return bb.array();
}
或者簡單一點:這可以用另一種方式來完成,例如,使用ByteBuffer
類
static byte[] toByteArray8(String s) {
ByteBuffer bb = ByteBuffer.allocate(16);
bb.asLongBuffer().put(Long.parseUnsignedLong(s.substring(0, 16), 16))
.put(Long.parseUnsignedLong(s.substring(16), 16));
return bb.array();
}
這樣,你不應該在乎的情況(你即使對於"000...000"
字符串,也總是會獲得16個字節),並且可能會有較少的堆分配。示例用法:
System.out.println(Arrays.toString(toByteArray("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")));
// [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
System.out.println(Arrays.toString(toByteArray("80000000000000000000000000000000")));
// [-128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
System.out.println(Arrays.toString(toByteArray("123FFFFFFFFFFFFFFFFFFFFFFFFFFFFF")));
// [18, 63, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
System.out.println(Arrays.toString(toByteArray("007FFFFFFFFFFFFFFFFFFFFFFFFFFFFF")));
// [0, 127, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
System.out.println(Arrays.toString(toByteArray("00000000000000000000000000000001")));
// [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
我發現很難嚴格遵循問題的情況。如果您發佈一個簡短但完整的程序來展示問題,即輸入,實際產出和預期產出,那麼它將會更容易幫助您。 –
由於Java的簽名性,當執行'toByteArray()'時,任何以'80'或更高開頭的值都會導致「額外」字節。 – Kayaman
Kayaman,所以除了這個額外的0之外沒有別的辦法嗎? :( –