В Java, как я могу преобразовать байтовый массив в строку шестнадцатеричных цифр, сохраняя ведущие нули? - PullRequest
156 голосов
/ 01 декабря 2008

Я работаю с примером кода Java для создания хэшей md5. Одна часть преобразует результаты из байтов в строку шестнадцатеричных цифр:

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 ]

5 голосов
/ 04 июня 2009

Другой вариант

public static String toHexString(byte[]bytes) {
    StringBuilder sb = new StringBuilder(bytes.length*2);
    for(byte b: bytes)
      sb.append(Integer.toHexString(b+0x800).substring(1));
    return sb.toString();
}
5 голосов
/ 02 декабря 2008

Это решение немного старше школы, и оно должно эффективно использовать память.

public static String toHexString(byte bytes[]) {
    if (bytes == null) {
        return null;
    }

    StringBuffer sb = new StringBuffer();
    for (int iter = 0; iter < bytes.length; iter++) {
        byte high = (byte) ( (bytes[iter] & 0xf0) >> 4);
        byte low =  (byte)   (bytes[iter] & 0x0f);
        sb.append(nibble2char(high));
        sb.append(nibble2char(low));
    }

    return sb.toString();
}

private static char nibble2char(byte b) {
    byte nibble = (byte) (b & 0x0f);
    if (nibble < 10) {
        return (char) ('0' + nibble);
    }
    return (char) ('a' + nibble - 10);
}
5 голосов
/ 07 апреля 2017

Я бы использовал что-то подобное для фиксированной длины, например, хэши:

md5sum = String.format("%032x", new BigInteger(1, md.digest()));

0 в маске выполняет заполнение ...

4 голосов
/ 13 июля 2010

Чтобы сохранить ведущие нули, вот небольшой вариант того, что предложил Пол (например, хэш md5):

public static String MD5hash(String text) throws NoSuchAlgorithmException {
    byte[] hash = MessageDigest.getInstance("MD5").digest(text.getBytes());
    return String.format("%032x",new BigInteger(1, hash));
}

Ой, это выглядит хуже, чем то, что предложил Айман, извините за это

4 голосов
/ 08 октября 2010
static String toHex(byte[] digest) {
    String digits = "0123456789abcdef";
    StringBuilder sb = new StringBuilder(digest.length * 2);
    for (byte b : digest) {
        int bi = b & 0xff;
        sb.append(digits.charAt(bi >> 4));
        sb.append(digits.charAt(bi & 0xf));
    }
    return sb.toString();
}
3 голосов
/ 29 июня 2009

Кажется, что функции concat и append могут быть очень медленными. Следующее было НАМНОГО быстрее для меня (чем мой предыдущий пост). Переход к массиву символов в построении вывода был ключевым фактором для его ускорения. Я не сравнивал Hex.encodeHex, предложенный Брэндоном Дюретом.

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[10000000];
    int c = 0;
    int v;
    for ( j = 0; j < bytes.length; j++ ) {
        v = bytes[j] & 0xFF;
        hexChars[c] = hexArray[v/16];
        c++;
        hexChars[c] = hexArray[v%16];
        c++;
    }
    return new String(hexChars, 0, c); }
2 голосов
/ 20 сентября 2012

Вы можете писать меньше без внешних библиотек:

String hex = (new HexBinaryAdapter()).marshal(md5.digest(YOUR_STRING.getBytes()))
2 голосов
/ 21 сентября 2012

Это решение не требует никакого сдвига или маскирования битов, таблиц поиска или внешних библиотек, и оно настолько короткое, насколько я могу получить:

byte[] digest = new byte[16];       

Formatter fmt = new Formatter();    
for (byte b : digest) { 
  fmt.format("%02X", b);    
}

fmt.toString()
2 голосов
/ 01 декабря 2008

Это то, что я использую для хэшей MD5:

public static String getMD5(String filename)
        throws NoSuchAlgorithmException, IOException {
    MessageDigest messageDigest = 
        java.security.MessageDigest.getInstance("MD5");

    InputStream in = new FileInputStream(filename);

    byte [] buffer = new byte[8192];
    int len = in.read(buffer, 0, buffer.length);

    while (len > 0) {
        messageDigest.update(buffer, 0, len);
        len = in.read(buffer, 0, buffer.length);
    }
    in.close();

    return new BigInteger(1, messageDigest.digest()).toString(16);
}

РЕДАКТИРОВАТЬ: Я проверил, и я заметил, что с этим также сокращаются конечные нули. Но это может произойти только в начале, так что вы можете сравнить с ожидаемой длиной и площадкой соответственно.

1 голос
/ 01 декабря 2008
byte messageDigest[] = algorithm.digest();
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < messageDigest.length; i++) {
    String hexByte = Integer.toHexString(0xFF & messageDigest[i]);
    int numDigits = 2 - hexByte.length();
    while (numDigits-- > 0) {
        hexString.append('0');
    }
    hexString.append(hexByte);
}
...