У меня есть массив байтов. Я хочу, чтобы каждая строка байтов этого массива была преобразована в соответствующие шестнадцатеричные значения.
Есть ли в Java какая-либо функция для преобразования байтового массива в шестнадцатеричный?
У меня есть массив байтов. Я хочу, чтобы каждая строка байтов этого массива была преобразована в соответствующие шестнадцатеричные значения.
Есть ли в Java какая-либо функция для преобразования байтового массива в шестнадцатеричный?
Ответы:
byte[] bytes = {-1, 0, 1, 2, 3 };
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02X ", b));
}
System.out.println(sb.toString());
// prints "FF 00 01 02 03 "
java.util.Formatter
синтаксис
%[flags][width]conversion
'0'
- результат будет дополнен нулями2
'X'
- результат форматируется как шестнадцатеричное целое, заглавныеГлядя на текст вопроса, также возможно, что это то, что запрашивается:
String[] arr = {"-1", "0", "10", "20" };
for (int i = 0; i < arr.length; i++) {
arr[i] = String.format("%02x", Byte.parseByte(arr[i]));
}
System.out.println(java.util.Arrays.toString(arr));
// prints "[ff, 00, 0a, 14]"
Несколько ответов здесь использует Integer.toHexString(int)
; это выполнимо, но с некоторыми оговорками. Так как параметр является int
расширением, преобразование примитива выполняется в byte
аргумент, который включает расширение знака.
byte b = -1;
System.out.println(Integer.toHexString(b));
// prints "ffffffff"
8-разрядный byte
, который подписан в Java, расширен до 32-разрядного знака int
. Чтобы эффективно отменить это расширение знака, можно замаскировать byte
с 0xFF
.
byte b = -1;
System.out.println(Integer.toHexString(b & 0xFF));
// prints "ff"
Другая проблема с использованием toHexString
заключается в том, что он не дополняется нулями:
byte b = 10;
System.out.println(Integer.toHexString(b & 0xFF));
// prints "a"
Оба этих фактора должны сделать String.format
решение более предпочтительным.
byte
, от -128
до 127
, включительноtoHexString
. Вы должны замаскировать это & 0xFF
, то Integer.toHexString(-46 & 0xFF)
есть "d2"
.
byte
значение & 0xFF
. format
решение выше , может также потребоваться маскирование в зависимости от того, что вы на самом деле , используя в качестве аргумента.
Я пишу, потому что ни один из существующих ответов не объясняет, почему их подходы работают, что я считаю действительно важным для этой проблемы. В некоторых случаях это приводит к тому, что предлагаемое решение кажется излишне сложным и тонким. Для иллюстрации я приведу довольно простой подход, но я предоставлю немного больше деталей , чтобы проиллюстрировать , почему это работает.
Прежде всего, что мы пытаемся сделать? Мы хотим преобразовать байтовое значение (или массив байтов) в строку, которая представляет шестнадцатеричное значение в ASCII. Итак, первый шаг - выяснить, что такое байт в Java:
Байтовый тип данных представляет собой 8-разрядное целое число со знаком в виде двоичного числа со знаком . Он имеет минимальное значение -128 и максимальное значение 127 (включительно). Байтовый тип данных может быть полезен для сохранения памяти в больших массивах, где экономия памяти действительно имеет значение. Их также можно использовать вместо int, где их пределы помогают уточнить ваш код; тот факт, что диапазон переменной ограничен, может служить формой документации.
Что это значит? Несколько вещей: во-первых, и самое главное, это означает, что мы работаем с 8-битными . Так, например, мы можем записать число 2 как 0000 0010. Однако, поскольку оно является дополнением до двух, мы пишем отрицательное число 2, например: 1111 1110. Что также означает, что преобразование в шестнадцатеричное является очень простым. То есть вы просто конвертируете каждый 4-битный сегмент прямо в гекс. Обратите внимание, что для понимания отрицательных чисел в этой схеме вам сначала нужно понять дополнение к двум. Если вы еще не понимаете дополнение к двум, вы можете прочитать отличное объяснение здесь: http://www.cs.cornell.edu/~tomf/notes/cps104/twoscomp.html
Как только число становится дополнением до двух, его очень просто преобразовать в гекс. В общем, преобразование из двоичного в шестнадцатеричное очень просто, и, как вы увидите в следующих двух примерах, вы можете перейти непосредственно от дополнения двух до шестнадцатеричного.
Пример 1: конвертировать 2 в шестнадцатеричное.
1) Сначала преобразуйте 2 в двоичный код в дополнении до двух:
2 (base 10) = 0000 0010 (base 2)
2) Теперь преобразуйте двоичный файл в гекс:
0000 = 0x0 in hex
0010 = 0x2 in hex
therefore 2 = 0000 0010 = 0x02.
Пример 2: конвертировать -2 (в дополнении до двух) в шестнадцатеричное.
1) Сначала преобразуйте -2 в двоичный код в дополнении до двух:
-2 (base 10) = 0000 0010 (direct conversion to binary)
1111 1101 (invert bits)
1111 1110 (add 1)
therefore: -2 = 1111 1110 (in two's complement)
2) Теперь преобразуйте в Hex:
1111 = 0xF in hex
1110 = 0xE in hex
therefore: -2 = 1111 1110 = 0xFE.
Теперь, когда мы рассмотрели эту концепцию, вы обнаружите, что мы можем достичь того, чего хотим, с помощью простой маскировки и сдвига. Главное, что нужно понять, это то, что байт, который вы пытаетесь преобразовать, уже дополняет два. Вы не делаете это преобразование самостоятельно. Я думаю, что это серьезная путаница в этом вопросе. Возьмем для примера следующий байтовый массив:
byte[] bytes = new byte[]{-2,2};
Мы просто вручную конвертировали их в шестнадцатеричные, но как мы можем это сделать на Java? Вот как:
Шаг 1: Создайте StringBuffer для хранения наших вычислений.
StringBuffer buffer = new StringBuffer();
Шаг 2. Изолируйте биты высшего порядка, преобразуйте их в шестнадцатеричные и добавьте в буфер.
Учитывая двоичное число 1111 1110, мы можем выделить биты более высокого порядка, сначала сместив их на 4, а затем обнулив оставшуюся часть числа. Логически это просто, однако детали реализации в Java (и многих языках) вносят помехи из-за расширения знака. По сути, когда вы сдвигаете значение байта, Java сначала преобразует ваше значение в целое число, а затем выполняет расширение знака. Таким образом, хотя вы ожидаете, что 1111 1110 >> 4 будет 0000 1111, в действительности на Java это представляется как дополнение к двум 0xFFFFFFFF!
Итак, возвращаясь к нашему примеру:
1111 1110 >> 4 (shift right 4) = 1111 1111 1111 1111 1111 1111 1111 1111 (32 bit sign-extended number in two's complement)
Затем мы можем выделить биты с помощью маски:
1111 1111 1111 1111 1111 1111 1111 1111 & 0xF = 0000 0000 0000 0000 0000 0000 0000 1111
therefore: 1111 = 0xF in hex.
В Java мы можем сделать все это одним выстрелом:
Character.forDigit((bytes[0] >> 4) & 0xF, 16);
Функция forDigit просто отображает переданное вами число на набор шестнадцатеричных чисел 0-F.
Шаг 3: Далее нам нужно выделить биты младшего разряда. Поскольку нужные нам биты уже находятся в правильном положении, мы можем просто замаскировать их:
1111 1110 & 0xF = 0000 0000 0000 0000 0000 0000 0000 1110 (recall sign extension from before)
therefore: 1110 = 0xE in hex.
Как и раньше, в Java мы можем сделать все это за один раз:
Character.forDigit((bytes[0] & 0xF), 16);
Собрав все это вместе, мы можем сделать это как цикл for и преобразовать весь массив:
for(int i=0; i < bytes.length; i++){
buffer.append(Character.forDigit((bytes[i] >> 4) & 0xF, 16));
buffer.append(Character.forDigit((bytes[i] & 0xF), 16));
}
Надеюсь, это объяснение прояснит ситуацию для тех, кто интересуется, что именно происходит во многих примерах, которые вы найдете в Интернете. Надеюсь, я не допустил вопиющих ошибок, но предложения и исправления приветствуются!
Character.digit()
, как(byte) ((Character.digit(str.charAt(0), 16) << 4) + Character.digit(str.charAt(1), 16))
Самый быстрый способ, который я пока нашел, это сделать следующее:
private static final String HEXES = "0123456789ABCDEF";
static String getHex(byte[] raw) {
final StringBuilder hex = new StringBuilder(2 * raw.length);
for (final byte b : raw) {
hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F)));
}
return hex.toString();
}
Это ~ в 50 раз быстрее чем String.format
. если вы хотите проверить это:
public class MyTest{
private static final String HEXES = "0123456789ABCDEF";
@Test
public void test_get_hex() {
byte[] raw = {
(byte) 0xd0, (byte) 0x0b, (byte) 0x01, (byte) 0x2a, (byte) 0x63,
(byte) 0x78, (byte) 0x01, (byte) 0x2e, (byte) 0xe3, (byte) 0x6c,
(byte) 0xd2, (byte) 0xb0, (byte) 0x78, (byte) 0x51, (byte) 0x73,
(byte) 0x34, (byte) 0xaf, (byte) 0xbb, (byte) 0xa0, (byte) 0x9f,
(byte) 0xc3, (byte) 0xa9, (byte) 0x00, (byte) 0x1e, (byte) 0xd5,
(byte) 0x4b, (byte) 0x89, (byte) 0xa3, (byte) 0x45, (byte) 0x35,
(byte) 0xd6, (byte) 0x10,
};
int N = 77777;
long t;
{
t = System.currentTimeMillis();
for (int i = 0; i < N; i++) {
final StringBuilder hex = new StringBuilder(2 * raw.length);
for (final byte b : raw) {
hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F)));
}
hex.toString();
}
System.out.println(System.currentTimeMillis() - t); // 50
}
{
t = System.currentTimeMillis();
for (int i = 0; i < N; i++) {
StringBuilder hex = new StringBuilder(2 * raw.length);
for (byte b : raw) {
hex.append(String.format("%02X", b));
}
hex.toString();
}
System.out.println(System.currentTimeMillis() - t); // 2535
}
}
}
Изменить : только что нашел что-то немного быстрее, и он держится на одной строке, но не совместим с JRE 9. Используйте на свой страх и риск
import javax.xml.bind.DatatypeConverter;
DatatypeConverter.printHexBinary(raw);
printHexBinary
из src.zip из jdk, который кажется в 1 раз быстрее, чем первый метод.
Попробуйте так:
byte bv = 10;
String hexString = Integer.toHexString(bv);
Работа с массивом (если я вас правильно понял):
byte[] bytes = {9, 10, 11, 15, 16};
StringBuffer result = new StringBuffer();
for (byte b : bytes) {
result.append(String.format("%02X ", b));
result.append(" "); // delimiter
}
return result.toString();
Как уже упоминалось, полигенные смазочные материалы String.format()
- это правильный ответ по сравнению с Integer.toHexString()
(поскольку он правильно работает с отрицательными числами).
-1
.
bv
этого возвращает один шестнадцатеричный символ . Принимая во внимание, что остальная часть кода возвращает строку шестнадцатеричных символов . Я изменил код с помощью разделителя, чтобы вы могли понять его сейчас.
Integer.toHexString
если вы маскируете byte
с, 0xFF
чтобы отменить расширение знака.
Лучшее решение - это задира:
String hex=DatatypeConverter.printHexBinary(byte[] b);
как упомянуто здесь
new BigInteger(byteArray).toString(16)
это путь тогда. Есть ли проблемы с этим?
Если вам нужно шестнадцатеричное представление постоянной ширины, т.е. 0A
вместо A
, чтобы вы могли однозначно восстановить байты, попробуйте format()
:
StringBuilder result = new StringBuilder();
for (byte bb : byteArray) {
result.append(String.format("%02X", bb));
}
return result.toString();
Короткий и простой способ преобразования byte[]
в шестнадцатеричную строку с помощью BigInteger
:
import java.math.BigInteger;
byte[] bytes = new byte[] {(byte)255, 10, 20, 30};
String hex = new BigInteger(1, bytes).toString(16);
System.out.println(hex); // ff0a141e
Класс встроенного системного класса java.math.BigInteger
( java.math.BigInteger ) совместим с двоичными и шестнадцатеричными данными:
BigInteger(signum=1, byte[])
для создания большого целого числа byte[]
(установите его первый параметр signum
= 1
для правильной обработки отрицательных байтов)BigInteger.toString(16)
для преобразования большого целого числа в шестнадцатеричную строкуnew BigInteger("ffa74b", 16)
- неправильно обрабатывает ведущий нольЕсли вы хотите иметь начальный ноль в шестнадцатеричном результате, проверьте его размер и добавьте недостающий ноль, если необходимо:
if (hex.length() % 2 == 1)
hex = "0" + hex;
Используйте new BigInteger(1, bytes)
вместо new BigInteger(bytes)
, потому что Java « разбита по дизайну », и byte
тип данных не содержит байтов, но подписан крошечными целыми числами [-128 ... 127]. Если первый байт отрицательный, BigInteger
предполагается, что вы передаете отрицательное большое целое число. Просто передайте в 1
качестве первого параметра ( signum=1
).
Обратное преобразование из шестнадцатеричного формата вbyte[]
хитрое: иногда в произведенный вывод входит ведущий ноль, и его следует очистить так:
byte[] bytes = new BigInteger("ffa74b", 16).toByteArray();
if (bytes[0] == 0) {
byte[] newBytes = new byte[bytes.length - 1];
System.arraycopy(bytes, 1, newBytes, 0, newBytes.length);
bytes = newBytes;
}
Последнее замечание: если у byte[]
него несколько ведущих нулей, они будут потеряны.
Если вы счастливы использовать внешнюю библиотеку, у org.apache.commons.codec.binary.Hex
класса есть encodeHex
метод, который принимает byte[]
и возвращает a char[]
. Этот метод НАМНОГО быстрее, чем опция формата, и включает в себя детали преобразования. Также поставляется с decodeHex
методом для обратного преобразования.
javax
пространство имен не всегда доступно.
Вы можете использовать метод из библиотеки Bouncy Castle Provider :
org.bouncycastle.util.encoders.Hex.toHexString(byteArray);
Пакет Bouncy Castle Crypto представляет собой реализацию криптографических алгоритмов на Java. Этот jar содержит провайдера JCE и облегченный API для API криптографии Bouncy Castle для JDK 1.5 до JDK 1.8.
Maven зависимость:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.60</version>
</dependency>
или из кодека Apache Commons :
org.apache.commons.codec.binary.Hex.encodeHexString(byteArray);
Пакет кодеков Apache Commons содержит простой кодер и декодеры для различных форматов, таких как Base64 и Hexadecimal. В дополнение к этим широко используемым кодерам и декодерам пакет кодеков также поддерживает набор утилит фонетического кодирования.
Maven зависимость:
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
</dependency>
Это код, который я нашел для запуска быстрее всего. Я запускал его на 109015 байтовых массивах длиной 32 в 23 мс. Я запускал его на виртуальной машине, так что, вероятно, он будет работать быстрее на голом металле.
public static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
public static char[] encodeHex( final byte[] data ){
final int l = data.length;
final char[] out = new char[l<<1];
for( int i=0,j=0; i<l; i++ ){
out[j++] = HEX_DIGITS[(0xF0 & data[i]) >>> 4];
out[j++] = HEX_DIGITS[0x0F & data[i]];
}
return out;
}
Тогда вы можете просто сделать
String s = new String( encodeHex(myByteArray) );
BigInteger n = new BigInteger(byteArray);
String hexa = n.toString(16));
BigInteger(byteArrayOf(-1, 2, 3, 4, 5)).toString(16)
возвращается"-fdfcfbfb"
(int) 255
), поскольку байты Java подписаны, поэтому результат должен быть FF02030405
. Если вы попробуете решение @Jerinaw выше, вы увидите, что оно выведет правильный вывод. Также см. Решение Светлина Накова ниже.
Вот простая функция для преобразования байта в шестнадцатеричный
private static String convertToHex(byte[] data) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < data.length; i++) {
int halfbyte = (data[i] >>> 4) & 0x0F;
int two_halfs = 0;
do {
if ((0 <= halfbyte) && (halfbyte <= 9))
buf.append((char) ('0' + halfbyte));
else
buf.append((char) ('a' + (halfbyte - 10)));
halfbyte = data[i] & 0x0F;
} while(two_halfs++ < 1);
}
return buf.toString();
}
Другие охватили общий случай. Но если у вас есть байтовый массив известной формы, например, MAC-адрес, то вы можете:
byte[] mac = { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 };
String str = String.format("%02X:%02X:%02X:%02X:%02X:%02X",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
Создание (и уничтожение) группы String
экземпляров не является хорошим способом, если производительность является проблемой.
Пожалуйста, игнорируйте эти подробные (повторяющиеся) аргументы, проверяющие операторы if
. Это для (других) образовательных целей.
Полный проект Maven: http://jinahya.googlecode.com/svn/trunk/com.googlecode.jinahya/hex-codec/
Кодирование ...
/**
* Encodes a single nibble.
*
* @param decoded the nibble to encode.
*
* @return the encoded half octet.
*/
protected static int encodeHalf(final int decoded) {
switch (decoded) {
case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x05:
case 0x06:
case 0x07:
case 0x08:
case 0x09:
return decoded + 0x30; // 0x30('0') - 0x39('9')
case 0x0A:
case 0x0B:
case 0x0C:
case 0x0D:
case 0x0E:
case 0x0F:
return decoded + 0x57; // 0x41('a') - 0x46('f')
default:
throw new IllegalArgumentException("illegal half: " + decoded);
}
}
/**
* Encodes a single octet into two nibbles.
*
* @param decoded the octet to encode.
* @param encoded the array to which each encoded nibbles are written.
* @param offset the offset in the array.
*/
protected static void encodeSingle(final int decoded, final byte[] encoded,
final int offset) {
if (encoded == null) {
throw new IllegalArgumentException("null encoded");
}
if (encoded.length < 2) {
// not required
throw new IllegalArgumentException(
"encoded.length(" + encoded.length + ") < 2");
}
if (offset < 0) {
throw new IllegalArgumentException("offset(" + offset + ") < 0");
}
if (offset >= encoded.length - 1) {
throw new IllegalArgumentException(
"offset(" + offset + ") >= encoded.length(" + encoded.length
+ ") - 1");
}
encoded[offset] = (byte) encodeHalf((decoded >> 4) & 0x0F);
encoded[offset + 1] = (byte) encodeHalf(decoded & 0x0F);
}
/**
* Decodes given sequence of octets into a sequence of nibbles.
*
* @param decoded the octets to encode
*
* @return the encoded nibbles.
*/
protected static byte[] encodeMultiple(final byte[] decoded) {
if (decoded == null) {
throw new IllegalArgumentException("null decoded");
}
final byte[] encoded = new byte[decoded.length << 1];
int offset = 0;
for (int i = 0; i < decoded.length; i++) {
encodeSingle(decoded[i], encoded, offset);
offset += 2;
}
return encoded;
}
/**
* Encodes given sequence of octets into a sequence of nibbles.
*
* @param decoded the octets to encode.
*
* @return the encoded nibbles.
*/
public byte[] encode(final byte[] decoded) {
return encodeMultiple(decoded);
}
Декодирование ...
/**
* Decodes a single nibble.
*
* @param encoded the nibble to decode.
*
* @return the decoded half octet.
*/
protected static int decodeHalf(final int encoded) {
switch (encoded) {
case 0x30: // '0'
case 0x31: // '1'
case 0x32: // '2'
case 0x33: // '3'
case 0x34: // '4'
case 0x35: // '5'
case 0x36: // '6'
case 0x37: // '7'
case 0x38: // '8'
case 0x39: // '9'
return encoded - 0x30;
case 0x41: // 'A'
case 0x42: // 'B'
case 0x43: // 'C'
case 0x44: // 'D'
case 0x45: // 'E'
case 0x46: // 'F'
return encoded - 0x37;
case 0x61: // 'a'
case 0x62: // 'b'
case 0x63: // 'c'
case 0x64: // 'd'
case 0x65: // 'e'
case 0x66: // 'f'
return encoded - 0x57;
default:
throw new IllegalArgumentException("illegal half: " + encoded);
}
}
/**
* Decodes two nibbles into a single octet.
*
* @param encoded the nibble array.
* @param offset the offset in the array.
*
* @return decoded octet.
*/
protected static int decodeSingle(final byte[] encoded, final int offset) {
if (encoded == null) {
throw new IllegalArgumentException("null encoded");
}
if (encoded.length < 2) {
// not required
throw new IllegalArgumentException(
"encoded.length(" + encoded.length + ") < 2");
}
if (offset < 0) {
throw new IllegalArgumentException("offset(" + offset + ") < 0");
}
if (offset >= encoded.length - 1) {
throw new IllegalArgumentException(
"offset(" + offset + ") >= encoded.length(" + encoded.length
+ ") - 1");
}
return (decodeHalf(encoded[offset]) << 4)
| decodeHalf(encoded[offset + 1]);
}
/**
* Encodes given sequence of nibbles into a sequence of octets.
*
* @param encoded the nibbles to decode.
*
* @return the encoded octets.
*/
protected static byte[] decodeMultiple(final byte[] encoded) {
if (encoded == null) {
throw new IllegalArgumentException("null encoded");
}
if ((encoded.length & 0x01) == 0x01) {
throw new IllegalArgumentException(
"encoded.length(" + encoded.length + ") is not even");
}
final byte[] decoded = new byte[encoded.length >> 1];
int offset = 0;
for (int i = 0; i < decoded.length; i++) {
decoded[i] = (byte) decodeSingle(encoded, offset);
offset += 2;
}
return decoded;
}
/**
* Decodes given sequence of nibbles into a sequence of octets.
*
* @param encoded the nibbles to decode.
*
* @return the decoded octets.
*/
public byte[] decode(final byte[] encoded) {
return decodeMultiple(encoded);
}
Это очень быстрый способ. Внешние библиотеки не нужны.
final protected static char[] HEXARRAY = "0123456789abcdef".toCharArray();
public static String encodeHexString( byte[] bytes ) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEXARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEXARRAY[v & 0x0F];
}
return new String(hexChars);
}
Я не мог понять, что именно вы имели в виду под байтовой строкой, но вот некоторые преобразования из байтовой в строковую и наоборот, конечно, в официальных документах намного больше
Integer intValue = 149;
Соответствующее значение байта:
Byte byteValue = intValue.byteValue(); // this will convert the rightmost byte of the intValue to byte, because Byte is an 8 bit object and Integer is at least 16 bit, and it will give you a signed number in this case -107
получить целочисленное значение из байтовой переменной:
Integer anInt = byteValue.intValue(); // This will convert the byteValue variable to a signed Integer
От байта и целого до шестнадцатеричной строки:
так я делаю:
Integer anInt = 149
Byte aByte = anInt.byteValue();
String hexFromInt = "".format("0x%x", anInt); // This will output 0x95
String hexFromByte = "".format("0x%x", aByte); // This will output 0x95
Преобразование массива байтов в шестнадцатеричную строку.
Насколько я знаю, не существует простой функции для преобразования всех элементов в одном массиве Object
в элементы другого Object
, поэтому вы должны сделать это самостоятельно. Вы можете использовать следующие функции:
От байта [] к строке:
public static String byteArrayToHexString(byte[] byteArray){
String hexString = "";
for(int i = 0; i < byteArray.length; i++){
String thisByte = "".format("%x", byteArray[i]);
hexString += thisByte;
}
return hexString;
}
И из шестнадцатеричной строки в байт []:
public static byte[] hexStringToByteArray(String hexString){
byte[] bytes = new byte[hexString.length() / 2];
for(int i = 0; i < hexString.length(); i += 2){
String sub = hexString.substring(i, i + 2);
Integer intVal = Integer.parseInt(sub, 16);
bytes[i / 2] = intVal.byteValue();
String hex = "".format("0x%x", bytes[i / 2]);
}
return bytes;
}
Слишком поздно, но я надеюсь, что это может помочь другим;)
Вот ваш быстрый метод:
private static final String[] hexes = new String[]{
"00","01","02","03","04","05","06","07","08","09","0A","0B","0C","0D","0E","0F",
"10","11","12","13","14","15","16","17","18","19","1A","1B","1C","1D","1E","1F",
"20","21","22","23","24","25","26","27","28","29","2A","2B","2C","2D","2E","2F",
"30","31","32","33","34","35","36","37","38","39","3A","3B","3C","3D","3E","3F",
"40","41","42","43","44","45","46","47","48","49","4A","4B","4C","4D","4E","4F",
"50","51","52","53","54","55","56","57","58","59","5A","5B","5C","5D","5E","5F",
"60","61","62","63","64","65","66","67","68","69","6A","6B","6C","6D","6E","6F",
"70","71","72","73","74","75","76","77","78","79","7A","7B","7C","7D","7E","7F",
"80","81","82","83","84","85","86","87","88","89","8A","8B","8C","8D","8E","8F",
"90","91","92","93","94","95","96","97","98","99","9A","9B","9C","9D","9E","9F",
"A0","A1","A2","A3","A4","A5","A6","A7","A8","A9","AA","AB","AC","AD","AE","AF",
"B0","B1","B2","B3","B4","B5","B6","B7","B8","B9","BA","BB","BC","BD","BE","BF",
"C0","C1","C2","C3","C4","C5","C6","C7","C8","C9","CA","CB","CC","CD","CE","CF",
"D0","D1","D2","D3","D4","D5","D6","D7","D8","D9","DA","DB","DC","DD","DE","DF",
"E0","E1","E2","E3","E4","E5","E6","E7","E8","E9","EA","EB","EC","ED","EE","EF",
"F0","F1","F2","F3","F4","F5","F6","F7","F8","F9","FA","FB","FC","FD","FE","FF"
};
public static String byteToHex(byte b) {
return hexes[b&0xFF];
}
Как и некоторые другие ответы, я рекомендую использовать String.format()
и BigInteger
. Но для интерпретации байтового массива как двоичного представления с прямым порядком байтов вместо двоичного представления с двумя дополнительными значениями (с сигнумом и неполным использованием диапазона возможных шестнадцатеричных значений) используйте BigInteger (int signum, byte [] magnitude) , а не BigInteger (byte [] val ) .
Например, для байтового массива длиной 8 используйте:
String.format("%016X", new BigInteger(1,bytes))
Преимущества:
Недостаток:
Пример:
byte[] bytes = new byte[8];
Random r = new Random();
System.out.println("big-endian | two's-complement");
System.out.println("-----------------|-----------------");
for (int i = 0; i < 10; i++) {
r.nextBytes(bytes);
System.out.print(String.format("%016X", new BigInteger(1,bytes)));
System.out.print(" | ");
System.out.print(String.format("%016X", new BigInteger(bytes)));
System.out.println();
}
Пример вывода:
big-endian | two's-complement
-----------------|-----------------
3971B56BC7C80590 | 3971B56BC7C80590
64D3C133C86CCBDC | 64D3C133C86CCBDC
B232EFD5BC40FA61 | -4DCD102A43BF059F
CD350CC7DF7C9731 | -32CAF338208368CF
82CDC9ECC1BC8EED | -7D3236133E437113
F438C8C34911A7F5 | -BC7373CB6EE580B
5E99738BE6ACE798 | 5E99738BE6ACE798
A565FE5CE43AA8DD | -5A9A01A31BC55723
032EBA783D2E9A9F | 032EBA783D2E9A9F
8FDAA07263217ABA | -70255F8D9CDE8546