Метод BigInteger.toString удаляет ведущий 0

Я пытаюсь сгенерировать сумму MD5, используя MessageDigest. И у меня есть следующий код.

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

Аргумент digit действителен, если 0 ‹=цифра ‹ основание.

Может ли кто-нибудь сказать мне, чем отличаются два метода и почему удаляется ведущий 0?


person Dheeraj Joshi    schedule 23.04.2012    source источник
comment
Вы говорите, что BigInteger.toString() должен выводить начальный ноль?   -  person Gabe    schedule 23.04.2012
comment
Все, что я спрашиваю, это почему toString удаляет начальный 0. ?   -  person Dheeraj Joshi    schedule 23.04.2012
comment
Да, и я получаю отрицательный голос, как будто это бесполезно. Боуху   -  person Dheeraj Joshi    schedule 23.04.2012
comment
Я не понимаю, что вы спрашиваете. Как toString должен знать, что вы ожидаете начальный 0? BigInteger хранит только число; он не знает, сколько начальных нулей вы ожидаете.   -  person Gabe    schedule 23.04.2012
comment
Подумайте об этом с другой стороны: чего вы ожидаете от new BigInteger("27").toString()? Сколько лидирующих нулей?   -  person yshavit    schedule 23.04.2012


Ответы (5)


Лично я избегал использования BigInteger для преобразования двоичных данных в текст. На самом деле он не для этого, даже если его можно использовать для этого. Существует множество кода для преобразования byte[] в его шестнадцатеричное представление - например. используя кодек Apache Commons или простой метод:

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);
}
person Jon Skeet    schedule 23.04.2012

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

куда

  1. 0 - нулевой ведущий знак
  2. 64 - длина строки
  3. X - верхний регистр
person Gorets    schedule 12.01.2016
comment
@Andro это ссылка на Cipher.getInstance(HMAC); - person Gorets; 16.02.2017

Он удален, потому что начальный ноль не имеет значения, согласно BigInteger. Между 27 и 000000000027 нет никакой разницы.

Если вам нужна определенная длина, вам придется заставить ее сделать что-то вроде:

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

(неуклюжий, хотя это).

person paxdiablo    schedule 23.04.2012

Удаленный ноль заменяется с помощью этого кода:

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

цикл будет учитывать столько начальных нулей, сколько необходимо

person user1689394    schedule 26.09.2012
comment
Думаю, Дирадж искал причины удаленного нуля. Не способ вернуть его. Кроме того, ваш код работает не так, как вы думаете. - person allingeek; 27.09.2012
comment
Извините, вы правы, но мой код работает, отправляя правильную контрольную сумму md5 на мой сервер. - person user1689394; 27.09.2012

person    schedule
comment
Проголосовали против, потому что ваш ответ неправильно отформатирован и не содержит никаких объяснений. - person Leroy; 11.02.2018
comment
Я исправил форматирование, но вам все еще нужно объяснить код. Кто-то пометил ваш ответ на удаление, но ответы, содержащие только код, не являются низкокачественными. Ваш ответ, похоже, является попыткой ответить на вопрос, поэтому его не следует помечать. Заслуживает ли это отрицательного голоса? Вполне возможно - я не могу комментировать его правильность или полезность - но я лично не голосовал. - person Wai Ha Lee; 11.02.2018