有人能解释从字节数组到十六进制字符串的转换吗?

abe*_*t80 4 java hex md5 bytearray

我最近开始研究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();
}
Run Code Online (Sandbox Code Playgroud)

我没有发现任何需要在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();
}
Run Code Online (Sandbox Code Playgroud)

为什么这样做也有效,哪种方式更有效?

谢谢你的时间.

tsc*_*ble 10

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

到目前为止......只需要进行基本设置并启动一个循环来遍历数组中的所有字节

        int halfbyte = (data[i] >>> 4) & 0x0F;
Run Code Online (Sandbox Code Playgroud)

转换为十六进制时的字节数是两个十六进制数字或8个二进制数字,具体取决于你查看它的基数.上面的语句将高4位向下移位(>>>是无符号右移)和逻辑与0000 1111进行对比,以便结果是一个等于字节高4位的整数(第一个十六进制数字).

说23是输入,这是二进制的0001 0111.移位使得逻辑AND将其转换为0000 0001.

        int two_halfs = 0;
        do {
Run Code Online (Sandbox Code Playgroud)

这只是设置do/while循环运行两次

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

这里我们显示实际的十六进制数字,基本上只使用零或一个字符作为起点并转换到正确的字符.第一个if语句覆盖所有数字0-9,第二个覆盖所有数字10-15(af为十六进制)

再次,使用我们的示例0000 0001十进制等于1.我们陷入上面的if块并将'1'加1以获得字符'1',将其附加到字符串并继续前进.

                halfbyte = data[i] & 0x0F;
Run Code Online (Sandbox Code Playgroud)

现在我们将整数设置为恰好等于字节中的低位并重复.

同样,如果我们的输入是23 ... 0001 0111,则逻辑AND变为0000 0111,即十进制7.重复上述相同的逻辑,显示字符"7".

            } while(two_halfs++ < 1);
Run Code Online (Sandbox Code Playgroud)

现在我们继续前进到数组中的下一个字节并重复.

        }
    return buf.toString();
}
Run Code Online (Sandbox Code Playgroud)

为了回答您的下一个问题,Java API已经有一个内置于BigInteger的基本转换实用程序.请参阅toString(int radix)文档.

不知道Java API使用的实现,我不能肯定地说,但我愿意打赌Java实现比你发布的第一个有点简单的算法更有效.