在Java中,如何将字节数组转换为十六进制字符串并保留前导零?

171

我正在使用一些用于生成MD5哈希的Java示例代码。其中一部分将结果从字节转换为十六进制数字字符串:

byte messageDigest[] = algorithm.digest();     
StringBuffer hexString = new StringBuffer();
for (int i=0;i<messageDigest.length;i++) {
    hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
    }

然而,这种方法并不完全有效,因为 toHexString 显然会删除前导零。那么,从字节数组转换为十六进制字符串并保留前导零的最简单方法是什么?

28个回答

0

在我看来,上面提供的所有解决方案都是错误的,因为它们提供了删除前导零的片段。

byte messageDigest[] = algorithm.digest();
for (int i = 0; i < messageDigest.length; i++) {
    hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
}    

根据此代码片段,迭代从字节数组中获取8位,将其转换为整数(因为Integer.toHexString函数需要int作为参数),然后将该整数转换为相应的哈希值。因此,例如,如果二进制中有00000001 00000001,根据代码,hexString变量将具有0x11作为十六进制值,而正确的值应该是0x0101。因此,在计算MD5时,我们可能会得到长度小于32字节的哈希值(由于缺少零),这可能不满足MD5哈希的加密唯一属性。
解决问题的方法是用以下代码片段替换上述代码片段:
byte messageDigest[] = algorithm.digest();
for (int i = 0; i < messageDigest.length; i++) {
    int temp=0xFF & messageDigest[i];
    String s=Integer.toHexString(temp);
    if(temp<=0x0F){
        s="0"+s;
    }
    hexString.append(s);
}

0

我很惊讶没有人提出以下解决方案:

StringWriter sw = new StringWriter();
com.sun.corba.se.impl.orbutil.HexOutputStream hex = new com.sun.corba.se.impl.orbutil.HexOutputStream(sw);
hex.write(byteArray);
System.out.println(sw.toString());

0

如何将 ASCII 转换回字节数组?

我按照 Jemenake 给出的以下代码进行 ASCII 转换。

public static String toHexString(byte[] bytes) {
    char[] hexArray = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
    char[] hexChars = new char[bytes.length * 2];
    int v;
    for ( int j = 0; j < bytes.length; j++ ) {
        v = bytes[j] & 0xFF;
        hexChars[j*2] = hexArray[v/16];
        hexChars[j*2 + 1] = hexArray[v%16];
    }
    return new String(hexChars);
}

0

这将为一个字节返回一个两个字符长的字符串。

public String toString(byte b){
    final char[] Hex = new String("0123456789ABCDEF").toCharArray();
    return  "0x"+ Hex[(b & 0xF0) >> 4]+ Hex[(b & 0x0F)];
}

0

我的变量

    StringBuilder builder = new StringBuilder();
    for (byte b : bytes)
    {
        builder.append(Character.forDigit(b/16, 16));
        builder.append(Character.forDigit(b % 16, 16));
    }
    System.out.println(builder.toString());

对我来说它有效。


0

这是一个有问题的解决方案吗?(Android Java)

    // Create MD5 Hash
    MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
    digest.update(s.getBytes());
    byte[] md5sum = digest.digest();
    BigInteger bigInt = new BigInteger(1, md5sum);
    String stringMD5 = bigInt.toString(16);
    // Fill to 32 chars
    stringMD5 = String.format("%32s", stringMD5).replace(' ', '0');
    return stringMD5;

基本上它会用0替换空格。


0

或者你可以这样做:

byte[] digest = algorithm.digest();
StringBuilder byteContet = new StringBuilder();
for(byte b: digest){
 byteContent = String.format("%02x",b);
 byteContent.append(byteContent);
}

这只是一个简短、简单的格式更改。


1
就快完成了...除了字节值是有符号的(-128 -> 127),所以你需要进行以下更改:byteContent = String.format("%02x",b&0xff); - RoyM
StringBuilder byteContet = new StringBuilder(); 看起来像是一个打字错误。 (byteContet) - Shafique Jamal

-1

这也是等效的,但使用Apache util HexBin更加简洁,代码可以简化为

HexBin.encode(messageDigest).toLowerCase();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接