Преобразовать строковое представление шестнадцатеричного дампа в байтовый массив, используя Java?

373

Я ищу способ конвертировать длинную строку (из дампа), которая представляет шестнадцатеричные значения в байтовом массиве.

Я не мог бы сформулировать это лучше, чем человек, который разместил здесь тот же вопрос .

Но чтобы сохранить оригинальность, я сформулирую это по-своему: предположим, у меня есть строка, "00A0BF"которую я хотел бы интерпретировать как

byte[] {0x00,0xA0,0xBf}

что мне делать?

Я новичок в Java и в итоге использовал BigIntegerи следил за ведущими шестнадцатеричными нулями. Но я думаю, что это ужасно, и я уверен, что упускаю что-то простое.

RAFRAF
источник
См. Также stackoverflow.com/questions/9655181/… .
flow2k
Я приручил BigInteger здесь .
Джон Макклейн
FWIW String.getBytes()не будет работать так, как вы думаете. Пришлось научиться этому нелегкому пути. if ("FF".getBytes() != "ff".getBytes()) { System.out.println("Try again"); }
tir38

Ответы:

637

Вот решение, которое я считаю лучше, чем любое опубликованное до сих пор:

public static byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                             + Character.digit(s.charAt(i+1), 16));
    }
    return data;
}

Причины, почему это улучшение:

  • Сейф с ведущими нулями (в отличие от BigInteger) и с отрицательными значениями байтов (в отличие от Byte.parseByte)

  • Не преобразует String в a char[]и не создает объекты StringBuilder и String для каждого байта.

  • Нет библиотечных зависимостей, которые могут быть недоступны

Не стесняйтесь добавлять проверку аргументов с помощью assertили исключений, если аргумент не известен как безопасный.

Дэйв Л.
источник
2
Можете ли вы привести пример, который неправильно декодирован, или объяснить, как это неправильно?
Дейв Л.
5
Это не работает для строки "0".
Выдает исключение
49
«0» не является допустимым вводом. Байты требуют двух шестнадцатеричных цифр каждый. Как отмечается в ответе: «Не стесняйтесь добавлять проверку аргументов ... если неизвестно, что аргумент безопасен».
Дэйв Л.
12
javax.xml.bind.DatatypeConverter.parseHexBinary (hexString), кажется, примерно на 20% быстрее, чем приведенное выше решение в моих микротестах (независимо от того, чего они мало стоят), а также правильно генерирует исключения при неверном вводе (например, «gg»). не является допустимым hexString, но вернет -77, используя предложенное решение).
Тревор Фриман
6
@DaedalusAlpha Это зависит от вашего контекста, но обычно я считаю, что лучше быстро и громко провалиться с такими вещами, чтобы вы могли исправить свои предположения, а не молча возвращать неверные данные.
Дэйв Л.
331

Однострочники:

import javax.xml.bind.DatatypeConverter;

public static String toHexString(byte[] array) {
    return DatatypeConverter.printHexBinary(array);
}

public static byte[] toByteArray(String s) {
    return DatatypeConverter.parseHexBinary(s);
}

Предупреждения :

  • в Java 9 Jigsaw он больше не является частью (по умолчанию) корневого набора java.se, поэтому он приведет к исключению ClassNotFoundException, если вы не укажете --add-modules java.se.ee (спасибо @ eckes)
  • Недоступно на Android (спасибо, что Fabianобратили на это внимание), но вы можете просто взять исходный код, если вашей системе javax.xmlпо какой-то причине не хватает . Спасибо @ Bert Regelinkза извлечение источника.
Владислав Раструсный
источник
14
ИМХО, это должен быть принятый / топовый ответ, так как он короткий и чистый (в отличие от ответа @ DaveL) и не требует никаких внешних библиотек (например, ответ Скаффмана). Кроме того, <Введите изношенную шутку о изобретении велосипеда> .
Priidu Neemre
9
Например, класс datatypeconverter недоступен в Android.
Фабиан
4
Предупреждение: в Java 9 Jigsaw это больше не является частью (по умолчанию) java.seкорневого набора, поэтому оно приведет к тому, что ClassNotFoundExceptionесли вы не укажете--add-modules java.se.ee
eckes
2
@dantebarba Я думаю, что javax.xml.bind.DatatypeConverterуже предоставляет метод для кодирования / декодирования данных Base64. Смотрите parseBase64Binary()и printBase64Binary().
DragShot
2
Чтобы добавить к проблемам DataTypeConverter, Java SE 11 полностью удалил JAXB API и теперь включен только в Java EE. Вы также можете добавить его как зависимость Maven, как это предлагается здесь: stackoverflow.com/a/43574427/7347751
Дэвид Мордигал
79

Класс Hex в commons-codec должен сделать это за вас.

http://commons.apache.org/codec/

import org.apache.commons.codec.binary.Hex;
...
byte[] decoded = Hex.decodeHex("00A0BF");
// 0x00 0xA0 0xBF
skaffman
источник
6
Это тоже выглядит хорошо. См. Org.apache.commons.codec.binary.Hex.decodeHex ()
Дейв Л.
Было интересно. Но я нашел их решение трудно следовать. Есть ли у него какие-либо преимущества по сравнению с тем, что вы предложили (кроме проверки четного числа символов)?
Рафраф
38

Теперь вы можете использовать BaseEncoding в guavaдля достижения этой цели .

BaseEncoding.base16().decode(string);

Чтобы изменить это, используйте

BaseEncoding.base16().encode(bytes);
jontro
источник
27

На самом деле, я думаю, что BigInteger - это очень хорошее решение:

new BigInteger("00A0BF", 16).toByteArray();

Изменить: Не безопасно для ведущих нулей , как отмечено на плакате.

Дэйв Л.
источник
Я тоже так думал изначально. И спасибо, что задокументировали это - я просто подумал, что должен ... он сделал несколько странных вещей, хотя я не совсем понял - например, пропустил несколько ведущих 0x00, а также смешал порядка 1 байта в 156-байтовой строке играл с.
Рафраф
2
Это хороший момент о ведении 0. Я не уверен, что верю, что это может смешать порядок байтов, и было бы очень интересно увидеть, как это будет продемонстрировано.
Дэйв Л.
1
да, как только я это сказал, я тоже не поверил :) Я провел сравнение байтового массива из BigInteger с mmyers'fromHexString и (без 0x00) с ошибочной строкой - они были идентичны. «Смешение» произошло, но это могло быть что-то еще. Завтра я
посмотрю
3
Проблема с BigInteger заключается в том, что должен быть «бит знака». Если для старшего байта установлен старший бит, то результирующий байтовый массив имеет дополнительный 0 в первой позиции. Но все равно +1.
серый
25

Однострочники:

import javax.xml.bind.DatatypeConverter;

public static String toHexString(byte[] array) {
    return DatatypeConverter.printHexBinary(array);
}

public static byte[] toByteArray(String s) {
    return DatatypeConverter.parseHexBinary(s);
}

Для тех из вас, кто интересуется реальным кодом One-liners от FractalizeR (мне нужно было это, поскольку javax.xml.bind недоступен для Android (по умолчанию)), это происходит из com.sun.xml.internal.bind. DatatypeConverterImpl.java :

public byte[] parseHexBinary(String s) {
    final int len = s.length();

    // "111" is not a valid hex encoding.
    if( len%2 != 0 )
        throw new IllegalArgumentException("hexBinary needs to be even-length: "+s);

    byte[] out = new byte[len/2];

    for( int i=0; i<len; i+=2 ) {
        int h = hexToBin(s.charAt(i  ));
        int l = hexToBin(s.charAt(i+1));
        if( h==-1 || l==-1 )
            throw new IllegalArgumentException("contains illegal character for hexBinary: "+s);

        out[i/2] = (byte)(h*16+l);
    }

    return out;
}

private static int hexToBin( char ch ) {
    if( '0'<=ch && ch<='9' )    return ch-'0';
    if( 'A'<=ch && ch<='F' )    return ch-'A'+10;
    if( 'a'<=ch && ch<='f' )    return ch-'a'+10;
    return -1;
}

private static final char[] hexCode = "0123456789ABCDEF".toCharArray();

public String printHexBinary(byte[] data) {
    StringBuilder r = new StringBuilder(data.length*2);
    for ( byte b : data) {
        r.append(hexCode[(b >> 4) & 0xF]);
        r.append(hexCode[(b & 0xF)]);
    }
    return r.toString();
}
Берт Регелинк
источник
3
DatatypeConverter также не доступен в Java 9 по умолчанию. Опасно то, что код, использующий его, будет компилироваться под Java 1.8 или более ранней (Java 9 с более ранними настройками исходного кода), но получит исключение времени выполнения под Java 9 без "--add-modules java.se.ee".
Стивен М-на забастовке -
24

HexBinaryAdapterПредоставляет возможность маршала и распаковать между Stringи byte[].

import javax.xml.bind.annotation.adapters.HexBinaryAdapter;

public byte[] hexToBytes(String hexString) {
     HexBinaryAdapter adapter = new HexBinaryAdapter();
     byte[] bytes = adapter.unmarshal(hexString);
     return bytes;
}

Это просто пример, который я напечатал ... Я на самом деле просто использую его как есть, и мне не нужно создавать отдельный метод для его использования.

GrkEngineer
источник
5
Это работает, только если входная строка (hexString) имеет четное количество символов. В противном случае: Исключение в потоке "main" java.lang.IllegalArgumentException: hexBinary должен быть четной длины:
ovdsrn
3
О, спасибо, что указал на это. У пользователя действительно не должно быть нечетного числа символов, потому что байтовый массив представлен как {0x00,0xA0,0xBf}. Каждый байт имеет две шестнадцатеричные цифры или кусочки. Поэтому любое количество байтов всегда должно иметь четное количество символов. Спасибо за упоминание этого.
GrkEngineer
8
Вы можете использовать java.xml.bind.DatatypeConverter.parseHexBinary (hexString) напрямую вместо использования HexBinaryAdapter (который, в свою очередь, вызывает DatatypeConverter). Таким образом, вам не нужно создавать объект экземпляра адаптера (поскольку методы DatatypeConverter являются статическими).
Тревор Фриман
javax.xml.bind. * больше не доступен в Java 9. Опасно то, что код, использующий его, будет компилироваться под Java 1.8 или более ранней (Java 9 с более ранними настройками исходного кода), но получит исключение времени выполнения, работающее под Java 9.
Стивен М - на забастовке -
15

Вот метод, который действительно работает (основан на нескольких предыдущих полу-правильных ответах):

private static byte[] fromHexString(final String encoded) {
    if ((encoded.length() % 2) != 0)
        throw new IllegalArgumentException("Input string must contain an even number of characters");

    final byte result[] = new byte[encoded.length()/2];
    final char enc[] = encoded.toCharArray();
    for (int i = 0; i < enc.length; i += 2) {
        StringBuilder curr = new StringBuilder(2);
        curr.append(enc[i]).append(enc[i + 1]);
        result[i/2] = (byte) Integer.parseInt(curr.toString(), 16);
    }
    return result;
}

Единственная возможная проблема, которую я вижу, - это если строка ввода очень длинная; вызов toCharArray () создает копию внутреннего массива строки.

РЕДАКТИРОВАТЬ: Да, и, кстати, байты подписаны в Java, поэтому ваша входная строка преобразуется в [0, -96, -65] вместо [0, 160, 191]. Но вы, наверное, уже знали это.

Майкл Майерс
источник
1
Спасибо Майкл - ты спасатель жизни! Работая над проектом BlackBerry и пытаясь преобразовать строковое представление байта обратно в байт ... используя метод RIM "Byte.parseByte (byteString, 16)". Продолжал бросать NumberFormatExcpetion. Потратил часы, пытаясь понять, почему. Ваше предложение "Integer.praseInt ()" сработало. Еще раз спасибо!!
BonanzaDriver
12

В Android, если вы работаете с hex, вы можете попробовать Okio .

простое использование:

byte[] bytes = ByteString.decodeHex("c000060000").toByteArray();

и результат будет

[-64, 0, 6, 0, 0]
Miao1007
источник
Я проверил много разных методов, но этот по крайней мере вдвое быстрее!
poby
5

BigInteger()Метод от java.math очень медленно и не рекомендуем.

Integer.parseInt(HEXString, 16)

может вызвать проблемы с некоторыми символами без преобразования в цифру / целое число

Хорошо работающий метод:

Integer.decode("0xXX") .byteValue()

Функция:

public static byte[] HexStringToByteArray(String s) {
    byte data[] = new byte[s.length()/2];
    for(int i=0;i < s.length();i+=2) {
        data[i/2] = (Integer.decode("0x"+s.charAt(i)+s.charAt(i+1))).byteValue();
    }
    return data;
}

Удачи, удачи

снайпер
источник
4

РЕДАКТИРОВАНИЕ: как указано @mmyers, этот метод не работает на вводе, который содержит подстроки, соответствующие байтам с установленным старшим битом ("80" - "FF"). Объяснение приведено в сообщении об ошибке: 6259307 Byte.parseByte не работает, как указано в документации SDK .

public static final byte[] fromHexString(final String s) {
    byte[] arr = new byte[s.length()/2];
    for ( int start = 0; start < s.length(); start += 2 )
    {
        String thisByte = s.substring(start, start+2);
        arr[start/2] = Byte.parseByte(thisByte, 16);
    }
    return arr;
}
Блэр Конрад
источник
1
Закрыть, но этот метод не работает на заданном входе "00A0BBF". См. Bugs.sun.com/bugdatabase/view_bug.do?bug_id=6259307 .
Майкл Майерс
1
Также странно, что это не имеет дело с "9C"
rafraf
1
@mmyers: воу. Это не хорошо. Извините за путаницу. @ravigad: 9C имеет ту же проблему, потому что в этом случае старший бит установлен.
Блэр Конрад
(byte) Short.parseShort (thisByte, 16) решает эту проблему
Джейми Хикс
3

Для чего стоит, вот еще одна версия, которая поддерживает строки нечетной длины, не прибегая к конкатенации строк.

public static byte[] hexStringToByteArray(String input) {
    int len = input.length();

    if (len == 0) {
        return new byte[] {};
    }

    byte[] data;
    int startIdx;
    if (len % 2 != 0) {
        data = new byte[(len / 2) + 1];
        data[0] = (byte) Character.digit(input.charAt(0), 16);
        startIdx = 1;
    } else {
        data = new byte[len / 2];
        startIdx = 0;
    }

    for (int i = startIdx; i < len; i += 2) {
        data[(i + 1) / 2] = (byte) ((Character.digit(input.charAt(i), 16) << 4)
                + Character.digit(input.charAt(i+1), 16));
    }
    return data;
}
Конор Свенссон
источник
2

Я всегда использовал такой метод, как

public static final byte[] fromHexString(final String s) {
    String[] v = s.split(" ");
    byte[] arr = new byte[v.length];
    int i = 0;
    for(String val: v) {
        arr[i++] =  Integer.decode("0x" + val).byteValue();

    }
    return arr;
}

этот метод разбивает на шестнадцатеричные значения, разделенные пробелом, но нетрудно разбить строку по любому другому критерию, например, по группам из двух символов.

pfranza
источник
Конкатенация строк не требуется. Просто используйте Integer.valueOf (val, 16).
Майкл Майерс
Я пытался использовать преобразования в основание, как это раньше, и у меня были смешанные результаты
pfranza
спасибо - как ни странно, он отлично работает с этой строкой: "9C001C" или "001C21" и завершается неудачно с этой строкой: "9C001C21" Исключение в потоке "main" java.lang.NumberFormatException: Для входной строки: "9C001C21" на java.lang. NumberFormatException.forInputString (Неизвестный источник)
rafraf
(Это не более странно, чем в Byte/ bytecase: старший бит установлен без старта -)
greybeard
2

Мне нравится решение Character.digit, но вот как я его решил

public byte[] hex2ByteArray( String hexString ) {
    String hexVal = "0123456789ABCDEF";
    byte[] out = new byte[hexString.length() / 2];

    int n = hexString.length();

    for( int i = 0; i < n; i += 2 ) {
        //make a bit representation in an int of the hex value 
        int hn = hexVal.indexOf( hexString.charAt( i ) );
        int ln = hexVal.indexOf( hexString.charAt( i + 1 ) );

        //now just shift the high order nibble and add them together
        out[i/2] = (byte)( ( hn << 4 ) | ln );
    }

    return out;
}
Ядро Паника
источник
2

Кодекс, представленный Бертом Регелинком, просто не работает. Попробуйте следующее:

import javax.xml.bind.DatatypeConverter;
import java.io.*;

public class Test
{  
    @Test
    public void testObjectStreams( ) throws IOException, ClassNotFoundException
    {     
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);

            String stringTest = "TEST";
            oos.writeObject( stringTest );

            oos.close();
            baos.close();

            byte[] bytes = baos.toByteArray();
            String hexString = DatatypeConverter.printHexBinary( bytes);
            byte[] reconvertedBytes = DatatypeConverter.parseHexBinary(hexString);

            assertArrayEquals( bytes, reconvertedBytes );

            ByteArrayInputStream bais = new ByteArrayInputStream(reconvertedBytes);
            ObjectInputStream ois = new ObjectInputStream(bais);

            String readString = (String) ois.readObject();

            assertEquals( stringTest, readString);
        }
    }
Шон Коффи
источник
2
На самом деле это другая проблема, и, вероятно, она относится к другому потоку.
Шон Коффи
1

Я обнаружил, что Kernel Panic предлагает наиболее полезное для меня решение, но столкнулся с проблемами, если шестнадцатеричная строка была нечетным числом. решил это так:

boolean isOdd(int value)
{
    return (value & 0x01) !=0;
}

private int hexToByte(byte[] out, int value)
{
    String hexVal = "0123456789ABCDEF"; 
    String hexValL = "0123456789abcdef";
    String st = Integer.toHexString(value);
    int len = st.length();
    if (isOdd(len))
        {
        len+=1; // need length to be an even number.
        st = ("0" + st);  // make it an even number of chars
        }
    out[0]=(byte)(len/2);
    for (int i =0;i<len;i+=2)
    {
        int hh = hexVal.indexOf(st.charAt(i));
            if (hh == -1)  hh = hexValL.indexOf(st.charAt(i));
        int lh = hexVal.indexOf(st.charAt(i+1));
            if (lh == -1)  lh = hexValL.indexOf(st.charAt(i+1));
        out[(i/2)+1] = (byte)((hh << 4)|lh);
    }
    return (len/2)+1;
}

Я добавляю количество шестнадцатеричных чисел в массив, поэтому я передаю ссылку на массив, который я использую, и int мне нужно преобразовать и вернуть относительную позицию следующего шестнадцатеричного числа. Таким образом, последний байтовый массив имеет [0] количество шестнадцатеричных пар, [1 ...] шестнадцатеричных пар, затем количество пар ...

Клейтон Балабанов
источник
1

Основываясь на предложенном решении, следующее должно быть немного более эффективным:

  public static byte [] hexStringToByteArray (final String s) {
    if (s == null || (s.length () % 2) == 1)
      throw new IllegalArgumentException ();
    final char [] chars = s.toCharArray ();
    final int len = chars.length;
    final byte [] data = new byte [len / 2];
    for (int i = 0; i < len; i += 2) {
      data[i / 2] = (byte) ((Character.digit (chars[i], 16) << 4) + Character.digit (chars[i + 1], 16));
    }
    return data;
  }

Потому что: первоначальное преобразование в массив char избавляет от проверки длины в charAt

Филип Хелгер
источник
1

Если в качестве стиля кодирования вы предпочитаете потоки Java 8, этого можно достичь, используя только примитивы JDK.

String hex = "0001027f80fdfeff";

byte[] converted = IntStream.range(0, hex.length() / 2)
    .map(i -> Character.digit(hex.charAt(i * 2), 16) << 4 | Character.digit(hex.charAt((i * 2) + 1), 16))
    .collect(ByteArrayOutputStream::new,
             ByteArrayOutputStream::write,
             (s1, s2) -> s1.write(s2.toByteArray(), 0, s2.size()))
    .toByteArray();

В , 0, s2.size()параметрах функции коллектора конкатенации могут быть опущены , если вы не против ловли IOException.

Энди Браун
источник
0
public static byte[] hex2ba(String sHex) throws Hex2baException {
    if (1==sHex.length()%2) {
        throw(new Hex2baException("Hex string need even number of chars"));
    }

    byte[] ba = new byte[sHex.length()/2];
    for (int i=0;i<sHex.length()/2;i++) {
        ba[i] = (Integer.decode(
                "0x"+sHex.substring(i*2, (i+1)*2))).byteValue();
    }
    return ba;
}
Дэвид V
источник
0

Мое официальное решение:

/**
 * Decodes a hexadecimally encoded binary string.
 * <p>
 * Note that this function does <em>NOT</em> convert a hexadecimal number to a
 * binary number.
 *
 * @param hex Hexadecimal representation of data.
 * @return The byte[] representation of the given data.
 * @throws NumberFormatException If the hexadecimal input string is of odd
 * length or invalid hexadecimal string.
 */
public static byte[] hex2bin(String hex) throws NumberFormatException {
    if (hex.length() % 2 > 0) {
        throw new NumberFormatException("Hexadecimal input string must have an even length.");
    }
    byte[] r = new byte[hex.length() / 2];
    for (int i = hex.length(); i > 0;) {
        r[i / 2 - 1] = (byte) (digit(hex.charAt(--i)) | (digit(hex.charAt(--i)) << 4));
    }
    return r;
}

private static int digit(char ch) {
    int r = Character.digit(ch, 16);
    if (r < 0) {
        throw new NumberFormatException("Invalid hexadecimal string: " + ch);
    }
    return r;
}

Это как функция PHP hex2bin (), но в стиле Java.

Пример:

String data = new String(hex2bin("6578616d706c65206865782064617461"));
// data value: "example hex data"
Даниэль Де Леон
источник
0

Поздно к вечеринке, но я объединил приведенный выше ответ DaveL в класс с обратным действием - на всякий случай, если это поможет.

public final class HexString {
    private static final char[] digits = "0123456789ABCDEF".toCharArray();

    private HexString() {}

    public static final String fromBytes(final byte[] bytes) {
        final StringBuilder buf = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            buf.append(HexString.digits[(bytes[i] >> 4) & 0x0f]);
            buf.append(HexString.digits[bytes[i] & 0x0f]);
        }
        return buf.toString();
    }

    public static final byte[] toByteArray(final String hexString) {
        if ((hexString.length() % 2) != 0) {
            throw new IllegalArgumentException("Input string must contain an even number of characters");
        }
        final int len = hexString.length();
        final byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
                    + Character.digit(hexString.charAt(i + 1), 16));
        }
        return data;
    }
}

И тестовый класс JUnit:

public class TestHexString {

    @Test
    public void test() {
        String[] tests = {"0FA1056D73", "", "00", "0123456789ABCDEF", "FFFFFFFF"};

        for (int i = 0; i < tests.length; i++) {
            String in = tests[i];
            byte[] bytes = HexString.toByteArray(in);
            String out = HexString.fromBytes(bytes);
            System.out.println(in); //DEBUG
            System.out.println(out); //DEBUG
            Assert.assertEquals(in, out);

        }

    }

}
DrPhill
источник
0

Я знаю, что это очень старая тема, но все равно хотел бы добавить свою копейку.

Если мне действительно нужно кодировать простую шестнадцатеричную строку в двоичный преобразователь, я бы хотел сделать это следующим образом.

public static byte[] hexToBinary(String s){

  /*
   * skipped any input validation code
   */

  byte[] data = new byte[s.length()/2];

  for( int i=0, j=0; 
       i<s.length() && j<data.length; 
       i+=2, j++)
  {
     data[j] = (byte)Integer.parseInt(s.substring(i, i+2), 16);
  }

  return data;
}
Tigger
источник
0

Далеко не самое чистое решение. Но это работает для меня и хорошо отформатировано:

private String createHexDump(byte[] msg, String description) {
    System.out.println();
    String result = "\n" + description;
    int currentIndex = 0;
    int printedIndex = 0;
    for(int i=0 ; i<msg.length ; i++){
        currentIndex++;
        if(i == 0){
            result += String.format("\n  %04x ", i);
        }
        if(i % 16 == 0 && i != 0){
            result += " | ";
            for(int j=(i-16) ; j<msg.length && j<i ; j++) {
                char characterToAdd = (char) msg[j];
                if (characterToAdd == '\n') {
                    characterToAdd = ' ';
                }
                result += characterToAdd;
                printedIndex++;
            }

            result += String.format("\n  %04x ", i);
        }

        result += String.format("%02x ", msg[i]);
    }

    if(currentIndex - printedIndex > 0){
        int leftOvers = currentIndex - printedIndex;
        for(int i=0 ; i<16-leftOvers ; i++){
            result += "   ";
        }

        result += " | ";

        for(int i=msg.length-leftOvers ; i<msg.length ; i++){
            char characterToAdd = (char) msg[i];
            if (characterToAdd == '\n') {
                characterToAdd = ' ';
            }
            result += characterToAdd;
        }
    }

    result += "\n";

    return result;
}

Выход:

  S -> C
    0000 0b 00 2e 06 4d 6f 72 69 74 7a 53 6f 6d 65 20 54  |  .Heyyy Some T
    0010 43 50 20 73 74 75 66 66 20 49 20 63 61 70 74 75  | CP stuff I captu
    0020 72 65 64 2e 2e 77 65 6c 6c 20 66 6f 72 6d 61 74  | red..well format
    0030 3f                                               | ?
Мориц Шмидт
источник
-2

Я думаю, сделаю это за вас. Я собрал его вместе из аналогичной функции, которая возвращала данные в виде строки:

private static byte[] decode(String encoded) {
    byte result[] = new byte[encoded/2];
    char enc[] = encoded.toUpperCase().toCharArray();
    StringBuffer curr;
    for (int i = 0; i < enc.length; i += 2) {
        curr = new StringBuffer("");
        curr.append(String.valueOf(enc[i]));
        curr.append(String.valueOf(enc[i + 1]));
        result[i] = (byte) Integer.parseInt(curr.toString(), 16);
    }
    return result;
}
Боб Кинг
источник
Во-первых, вам не нужно преобразовывать строку в верхний регистр. Во-вторых, можно добавлять символы непосредственно в StringBuffer, что должно быть гораздо более эффективным.
Майкл Майерс
-2

Для меня это было решение, HEX = "FF01", затем разделить на FF (255) и 01 (01)

private static byte[] BytesEncode(String encoded) {
    //System.out.println(encoded.length());
    byte result[] = new byte[encoded.length() / 2];
    char enc[] = encoded.toUpperCase().toCharArray();
    String curr = "";
    for (int i = 0; i < encoded.length(); i=i+2) {
        curr = encoded.substring(i,i+2);
        System.out.println(curr);
        if(i==0){
            result[i]=((byte) Integer.parseInt(curr, 16));
        }else{
            result[i/2]=((byte) Integer.parseInt(curr, 16));
        }

    }
    return result;
}
Alejandro
источник
На этот вопрос уже давно дан ответ, и у него есть несколько хороших альтернатив; К сожалению, ваш ответ не дает сколько-нибудь значительного улучшения на данный момент.
rfornal