簡體   English   中英

有人能解釋從字節數組到十六進制字符串的轉換嗎?

[英]Can someone explain the conversion from byte array to hex string?

我最近開始研究MD5哈希(用Java),雖然我找到了幫助我實現這一目標的算法和方法,但我還是想知道它是如何工作的。

首先,我從以下網址找到以下內容:

private static String convertToHex(byte[] data) {
    StringBuffer buf = new StringBuffer();
    for (int i = 0; i < data.length; i++) {
        int halfbyte = (data[i] >>> 4) & 0x0F;
        int two_halfs = 0;
        do {
            if ((0 <= halfbyte) && (halfbyte <= 9))
                buf.append((char) ('0' + halfbyte));
            else
                buf.append((char) ('a' + (halfbyte - 10)));
                halfbyte = data[i] & 0x0F;
            } while(two_halfs++ < 1);
        }
    return buf.toString();
}

我沒有發現在Java中使用位移的任何需要,所以我對此有點生疏。 有人足以說明(簡單來說)上述代碼究竟是如何進行轉換的? “>>>”?

我還在StackOverflow上找到了其他解決方案,例如這里這里 ,它使用了BigInteger:

try {
   String s = "TEST STRING";
   MessageDigest md5 = MessageDigest.getInstance("MD5");
   md5.update(s.getBytes(),0,s.length());
   String signature = new BigInteger(1,md5.digest()).toString(16);
   System.out.println("Signature: "+signature);

} catch (final NoSuchAlgorithmException e) {
   e.printStackTrace();
}

為什么這樣做也有效,哪種方式更有效?

謝謝你的時間。

private static String convertToHex(byte[] data) {
    StringBuffer buf = new StringBuffer();
    for (int i = 0; i < data.length; i++) {

到目前為止......只需要進行基本設置並啟動一個循環來遍歷數組中的所有字節

        int halfbyte = (data[i] >>> 4) & 0x0F;

轉換為十六進制時的字節數是兩個十六進制數字或8個二進制數字,具體取決於你查看它的基數。上面的語句將高4位向下移位(>>>是無符號右移)和邏輯與0000 1111進行對比,以便結果是一個等於字節高4位的整數(第一個十六進制數字)。

說23是輸入,這是二進制的0001 0111。 移位使得邏輯AND將其轉換為0000 0001。

        int two_halfs = 0;
        do {

這只是設置do / while循環運行兩次

            if ((0 <= halfbyte) && (halfbyte <= 9))
                buf.append((char) ('0' + halfbyte));
            else
                buf.append((char) ('a' + (halfbyte - 10)));

這里我們顯示實際的十六進制數字,基本上只使用零或一個字符作為起點並轉換到正確的字符。 第一個if語句覆蓋所有數字0-9,第二個覆蓋所有數字10-15(af為十六進制)

再次,使用我們的示例0000 0001十進制等於1.我們陷入上面的if塊並將'1'加1以獲得字符'1',將其附加到字符串並繼續前進。

                halfbyte = data[i] & 0x0F;

現在我們將整數設置為恰好等於字節中的低位並重復。

同樣,如果我們的輸入是23 ... 0001 0111,則邏輯AND變為0000 0111,即十進制7。 重復上述相同的邏輯,顯示字符“7”。

            } while(two_halfs++ < 1);

現在我們繼續前進到數組中的下一個字節並重復。

        }
    return buf.toString();
}

為了回答您的下一個問題,Java API已經有一個內置於BigInteger的基本轉換實用程序。 請參閱toString(int radix)文檔。

不知道Java API使用的實現,我不能肯定地說,但我願意打賭Java實現比你發布的第一個有點簡單的算法更有效。

要回答這個問題:

為什么這也有效

它沒有。 至少,與循環版本不同。 new BigInteger(...)。toString(16)將不會顯示前一版本的前導零。 通常對於寫出一個字節數組(特別是一個代表哈希的東西),你會想要一個固定長度的輸出,所以如果你想使用那個版本,你必須適當地填充它。

有關位移的詳細說明,請查看以下SO問題中的答案。 什么是按位移位(位移)運算符以及它們如何工作?

他似乎試圖將一個單字節轉換為一個小於16的數字,這樣他就可以很容易地確定該字節用代碼表示的那個字符。

  if ((0 <= halfbyte) && (halfbyte <= 9))
                buf.append((char) ('0' + halfbyte));
            else
                buf.append((char) ('a' + (halfbyte - 10)));

這是一個簡單的答案,但我不是那么明亮無論如何= D.

這些東西你不必自己編寫,因為它已經用apache-commons-codec編寫了:

import org.apache.commons.codec.binary.Hex;
...
Hex.encodeHexString(byte[] array)

Hex類中有許多更有用的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM