【问题标题】:BigInteger.toString method is deleting leading 0BigInteger.toString 方法正在删除前导 0
【发布时间】:2012-05-03 18:47:10
【问题描述】:

我正在尝试使用 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));

并且输出符合预期。

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

Character.forDigit 提供的数字到字符的映射是 使用,如果合适的话,前面会加上一个减号。

在 Character.forDigit 方法中

如果 0 ,则 digit 参数有效

谁能告诉我这两种方法有何不同以及为什么要删除前导 0?

【问题讨论】:

  • 你是说BigInteger.toString()应该输出一个前导零?
  • 我要问的是为什么 toString 正在删除前导 0。?
  • 是的,我得到了反对票,好像它没有用一样。嘘
  • 我不明白你在问什么。 toString 应该如何知道你期待一个领先的 0? BigInteger 只存储一个数字;它不知道您期望有多少个前导零。
  • 换个角度想一想:你对new BigInteger("27").toString()有什么期望?有多少个前导零?

标签: java tostring biginteger


【解决方案1】:

我个人避免使用BigInteger 将二进制数据转换为文本。这并不是它的真正用途,即使它可以用于此目的。有大量代码可用于将 byte[] 转换为其十六进制表示形式 - 例如使用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);
}

【讨论】:

    【解决方案2】:

    String.format("%064X", new BigInteger(1, 字节数组);

    在哪里

    1. 0 - 前导零符号
    2. 64 - 字符串长度
    3. X - 大写
    4. ByteArray - 要在其上运行此操作的 ByteArray

    【讨论】:

    • @Andro 链接到 Cipher.getInstance("HMAC");
    【解决方案3】:

    根据BigInteger,它被删除是因为前导零不重要。 27000000000027 没有区别。

    如果你想要一个特定的长度,你必须自己强制,比如:

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

    (虽然很笨拙)。

    【讨论】:

      【解决方案4】:

      使用此代码替换删除的零:

      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;
          }
      

      循环将根据需要考虑尽可能多的前导零

      【讨论】:

      • 我认为 Dheeraj 正在寻找删除零的原因。没有办法找回来。此外,您的代码并不像您认为的那样工作。
      • 抱歉,您是对的,但我的代码确实可以将正确的 md5 校验和发送到我的服务器。
      【解决方案5】:
      MessageDigest m=MessageDigest.getInstance("MD5");
      m.update(PlainText.getBytes(),0,PlainText.length());
      String M1=new BigInteger(1,m.digest()).toString(16);      
      return M1;
      

      【讨论】:

      • 投了反对票,因为您的答案格式不正确,并且不包含任何解释。
      • 我已经修复了格式,但您仍然需要解释代码。有人flagged your answer for deletion,但code-only answers are not low-quality。您的回答似乎是试图回答问题,因此不应被标记。它值得被否决吗?很有可能——我无法评论它的正确性或有用性——但我个人并没有投反对票。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-28
      • 2012-02-08
      • 1970-01-01
      • 1970-01-01
      • 2022-12-18
      相关资源
      最近更新 更多