BigInteger.toString方法正在删除前导0

我正在尝试使用MessageDigest生成MD5总和。 我有以下代码。

byte[] md5sum = digest.digest(); BigInteger bigInt = new BigInteger(1, md5sum); output = bigInt.toString(16); 

这不返回32个字符串,而是返回31个字符的字符串8611c0b0832bce5a19ceee626a403a7

预期字符串是08611c0b0832bce5a19ceee626a403a7

输出中缺少前导0。

我尝试了另一种方法

 byte[] md5sum = digest.digest(); output = new String(Hex.encodeHex(md5sum)); 

输出正如预期的那样。

我检查了doc,Integer.toString根据它进行了转换

使用Character.forDigit提供的数字到字符映射,如果合适,前缀为减号。

并在Character.forDigit方法

如果0 <= digit <radix,则数字参数有效。

有人可以告诉我两种方法有何不同以及为什么前导0被删除?

我个人会避免使用BigInteger将二进制数据转换为文本。 这并不是它的真正含义,即使它可以用于此。 有很多代码可用于将byte[]转换为hex表示 – 例如使用Apache Commons Codec或简单的单一方法:

 private static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray(); public static String toHex(byte[] data) { char[] chars = new char[data.length * 2]; for (int i = 0; i < data.length; i++) { chars[i * 2] = HEX_DIGITS[(data[i] >> 4) & 0xf]; chars[i * 2 + 1] = HEX_DIGITS[data[i] & 0xf]; } return new String(chars); } 

根据BigInteger说法,它被删除了,因为前导零并不重要。 27000000000027之间没有区别。

如果你想要一个特定的长度,你必须自己强迫它,例如:

 output = ("00000000000000000000000000000000"+output).substring(output.length()); 

(尽管那是kludgy)。

String.format(“%064X”,new BigInteger(1,hmac.doFinal(message.getBytes())));

哪里

  1. 0 – 零前导符号
  2. 64 – 字符串长度
  3. X – 大写

使用以下代码替换已删除的零:

 MessageDigest digest = MessageDigest.getInstance("MD5"); digest.reset(); digest.update(output.getBytes()); byte[] outDigest = digest.digest(); BigInteger outBigInt = new BigInteger(1,outDigest); output = outBigInt.toString(16); while (output.length() < 32){ output = "0"+output; } 

循环将根据需要占据多个前导零

 MessageDigest m=MessageDigest.getInstance("MD5"); m.update(PlainText.getBytes(),0,PlainText.length()); String M1=new BigInteger(1,m.digest()).toString(16); return M1;