web-dev-qa-db-ja.com

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

そして、出力は期待どおりです。

ドキュメントを確認すると、Integer.toStringがそれに応じて変換を行います

Character.forDigitによって提供される数字から文字へのマッピングが使用され、必要に応じてマイナス記号が付加されます。

およびCharacter.forDigitメトス

桁引数は、0 <=桁<基数の場合に有効です。

2つの方法の違いと、先頭の0が削除される理由を教えてもらえますか?

27
Dheeraj Joshi

私は個人的にavoidBigIntegerを使用してバイナリデータをテキストに変換します。 を使用できるとしても、それは実際にはその目的ではありません。 byte[]を16進表現に変換するために利用できるコードがたくさんあります。 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);
}
19
Jon Skeet

BigIntegerによると、先行ゼロは重要ではないため、削除されています。 27000000000027の間に違いはありません。

特定の長さが必要な場合は、次のように自分で強制する必要があります。

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

(それは厄介ですが)。

8
paxdiablo

String.format( "%064X"、new BigInteger(1、hmac.doFinal(message.getBytes())));

どこ

  1. 0-ゼロ先行記号
  2. 64-文字列の長さ
  3. X-大文字
8
Gorets

削除されたゼロは、次のコードを使用して置き換えられます。

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

ループは必要な数の先行ゼロを考慮します

2
user1689394