Converter uma representação de string de um hex dump em uma matriz de bytes usando Java?

372

Eu estou procurando uma maneira de converter uma seqüência longa (de um despejo), que representa valores hexadecimais em uma matriz de bytes.

Eu não poderia ter formulado melhor do que a pessoa que postou a mesma pergunta aqui .

Mas, para mantê-lo original, vou dizer do meu jeito: suponha que eu tenha uma string "00A0BF"que gostaria de interpretar como a

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

O que devo fazer?

Eu sou um novato em Java e acabei usando BigIntegere cuidando dos principais zeros hexadecimais. Mas acho feio e tenho certeza de que estou perdendo algo simples.

rafraf
fonte
Consulte também stackoverflow.com/questions/9655181/… .
flow2k
Eu domado BigInteger aqui .
John McClane
O FWIW String.getBytes()não funcionará como você pensa. Tive que aprender isso da maneira mais difícil. if ("FF".getBytes() != "ff".getBytes()) { System.out.println("Try again"); }
tir38

Respostas:

636

Aqui está uma solução que eu acho melhor do que qualquer outra postada até agora:

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

Razões pelas quais é uma melhoria:

  • Seguro com zeros à esquerda (ao contrário do BigInteger) e com valores de bytes negativos (ao contrário de Byte.parseByte)

  • Não converte a String em um char[]nem cria objetos StringBuilder e String para cada byte.

  • Nenhuma dependência de biblioteca que pode não estar disponível

Sinta-se à vontade para adicionar verificação de argumento por meio de assertou exceções, se o argumento não for seguro.

Dave L.
fonte
2
Você pode dar um exemplo decodificado incorretamente ou explicar como está errado?
Dave L.
5
Não funciona para a String "0". Ele lança uma java.lang.StringIndexOutOfBoundsException
ovdsrn
49
"0" não é uma entrada válida. Os bytes requerem dois dígitos hexidecimais cada. Como a resposta observa, "Sinta-se à vontade para adicionar verificação de argumento ... se o argumento não for seguro".
9788 Dave
12
javax.xml.bind.DatatypeConverter.parseHexBinary (hexString) parece ser cerca de 20% mais rápido que a solução acima em meus microtestes (por pouco que valham a pena), além de lançar corretamente exceções em entradas inválidas (por exemplo, "gg" não é um hexString válido, mas retornará -77 usando a solução conforme proposta).
Trevor Freeman
6
@DaedalusAlpha Depende do seu contexto, mas geralmente acho melhor falhar rápido e alto com essas coisas, para que você possa corrigir suas suposições em vez de retornar dados incorretos silenciosamente.
Dave L.
331

One-liners:

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

Advertências :

  • no Java 9 Jigsaw, isso não faz mais parte do conjunto raiz (padrão) java.se, portanto resultará em uma ClassNotFoundException, a menos que você especifique --add-modules java.se.ee (graças a @ eckes)
  • Não está disponível no Android (obrigado Fabianpor observar isso), mas você pode usar o código-fonte se o seu sistema faltar javax.xmlpor algum motivo. Obrigado a @ Bert Regelinkpor extrair a fonte.
Vladislav Rastrusny
fonte
14
IMHO, esta deve ser a resposta aceita / superior, pois é curta e limpa (ao contrário da resposta de @ DaveL) e não requer nenhuma biblioteca externa (como a resposta de skaffman). Além disso, <Digite uma piada gasta sobre reinventar a bicicleta> .
Priidu Neemre
9
a classe datatypeconverter não está disponível no android, por exemplo.
Fabio
4
Aviso: no Java 9 Jigsaw isso não faz mais parte do java.seconjunto raiz (padrão) , portanto resultará em um, a ClassNotFoundExceptionmenos que você especifique--add-modules java.se.ee
eckes
2
@dantebarba Acho que javax.xml.bind.DatatypeConverterjá fornece um método para codificar / decodificar dados Base64. Veja parseBase64Binary()e printBase64Binary().
DragShot
2
Para aumentar os problemas DataTypeConverter, o Java SE 11 removeu completamente a API JAXB e agora está incluído apenas no Java EE. Você também pode adicioná-lo como uma dependência do Maven, conforme sugerido aqui: stackoverflow.com/a/43574427/7347751
David Mordigal
79

A classe Hex no commons-codec deve fazer isso por você.

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

import org.apache.commons.codec.binary.Hex;
...
byte[] decoded = Hex.decodeHex("00A0BF");
// 0x00 0xA0 0xBF
skaffman
fonte
6
Isso também parece bom. Veja org.apache.commons.codec.binary.Hex.decodeHex ()
Dave L.
Foi interessante. Mas achei difícil a solução deles. Tem alguma vantagem sobre o que você propôs (além de verificar o número par de caracteres)?
rafraf 27/09/08
38

Agora você pode usar BaseEncoding no guavapara alcançar este objetivo.

BaseEncoding.base16().decode(string);

Para inverter, use

BaseEncoding.base16().encode(bytes);
Jontro
fonte
27

Na verdade, acho que a solução BigInteger é muito boa:

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

Edit: Não é seguro para zeros à esquerda , conforme observado no pôster.

Dave L.
fonte
Eu também pensei assim inicialmente. E obrigado por documentá-lo - eu estava pensando que deveria ... fez algumas coisas estranhas que eu realmente não entendi - como omitir alguns 0x00 iniciais e também misturar a ordem de 1 byte em uma string de 156 bytes I estava brincando com.
rafraf 26/09/08
2
Esse é um bom argumento sobre os 0s iniciais. Não tenho certeza se acredito que possa misturar a ordem dos bytes e ficaria muito interessado em vê-lo demonstrado.
Dave L.
11
sim, assim que eu disse isso, também não acreditei em mim :) Fiz uma comparação da matriz de bytes do BigInteger com mmyers'from HexString e (sem 0x00) contra a string incorreta - eles eram idênticos. A "confusão" aconteceu, mas pode ter sido outra coisa. I willlook mais de perto amanhã
Rafraf
3
O problema com o BigInteger é que deve haver um "bit de sinal". Se o byte inicial tiver o bit alto definido, a matriz de bytes resultante terá um 0 extra na 1ª posição. Mas ainda +1.
cinza
25

One-liners:

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

Para aqueles que estão interessados ​​no código real por trás dos One-liners do FractalizeR (eu precisava que, já que o javax.xml.bind não estivesse disponível para Android (por padrão)), isso vem de 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();
}
Bert Regelink
fonte
3
DatatypeConverter também não está disponível no Java 9 por padrão. O mais perigoso é o código que ele compila no Java 1.8 ou anterior (Java 9 com configurações de origem anteriores), mas obtém uma exceção de tempo de execução no Java 9 sem "--add-modules java.se.ee".
precisa saber é o seguinte
24

O HexBinaryAdapterfornece a capacidade de empacotar e desempacotar entre Stringe byte[].

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

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

Esse é apenas um exemplo que eu digitei ... Na verdade, eu apenas o uso como está e não preciso criar um método separado para usá-lo.

GrkEngineer
fonte
5
Funciona apenas se a sequência de entrada (hexString) tiver um número par de caracteres. Caso contrário: A exceção no encadeamento "main" java.lang.IllegalArgumentException: hexBinary precisa ser uniforme:
ovdsrn
3
Oh, obrigado por apontar isso. Um usuário realmente não deve ter um número ímpar de caracteres porque a matriz de bytes é representada como {0x00,0xA0,0xBf}. Cada byte possui dois dígitos hexadecimais ou mordidelas. Portanto, qualquer número de bytes sempre deve ter um número par de caracteres. Obrigado por mencionar isso.
GrkEngineer
8
Você pode usar java.xml.bind.DatatypeConverter.parseHexBinary (hexString) diretamente em vez de usar HexBinaryAdapter (que por sua vez chama DatatypeConverter). Dessa forma, você não precisa criar um objeto de instância do adaptador (pois os métodos DatatypeConverter são estáticos).
Trevor Freeman
javax.xml.bind. * não está mais disponível no Java 9. O mais perigoso é o código que ele compila no Java 1.8 ou anterior (Java 9 com configurações de origem anteriores), mas obtém uma exceção de tempo de execução em execução no Java 9.
Stephen M -on strike-
15

Aqui está um método que realmente funciona (com base em várias respostas semi-corretas anteriores):

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

O único problema possível que posso ver é se a string de entrada é extremamente longa; chamar toCharArray () faz uma cópia da matriz interna da string.

EDIT: Ah, e, a propósito, os bytes são assinados em Java; portanto, sua string de entrada é convertida em [0, -96, -65] em vez de [0, 160, 191]. Mas você provavelmente já sabia disso.

Michael Myers
fonte
11
Obrigado Michael - você salva vidas! Trabalhando em um projeto BlackBerry e tentando converter uma representação de seqüência de caracteres de um byte de volta em byte ... usando o método "Byte.parseByte (byteString, 16)" da RIM. Mantido lançando um NumberFormatExcpetion. Passou horas se esforçando para descobrir o porquê. Sua sugestão de "Integer.praseInt ()" fez o truque. Obrigado novamente!!
BonanzaDriver 23/10/11
12

No android, se você estiver trabalhando com hex, poderá tentar o okio .

uso simples:

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

e o resultado será

[-64, 0, 6, 0, 0]
Miao1007
fonte
Eu testei muitos métodos diferentes, mas este é pelo menos duas vezes mais rápido!
poby
5

O BigInteger()método de java.math é muito lento e não é recomendável.

Integer.parseInt(HEXString, 16)

pode causar problemas com alguns caracteres sem converter para dígito / número inteiro

um método de trabalho bem:

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

Função:

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

Divirta-se, boa sorte

Franco atirador
fonte
4

EDIT: como apontado por @mmyers, esse método não funciona na entrada que contém substrings correspondentes a bytes com o conjunto de bits alto ("80" - "FF"). A explicação está na identificação do bug: 6259307 Byte.parseByte não está funcionando conforme anunciado na documentação do 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;
}
Blair Conrad
fonte
11
Feche, mas este método falha na entrada "00A0BBF" especificada. Consulte bugs.sun.com/bugdatabase/view_bug.do?bug_id=6259307 .
Michael Myers
11
Também estranhamente ele não lidar com "9C"
Rafraf
11
@ mmyers: whoa. Isso não é bom. Desculpe pela confusão. @ravigad: 9C tem o mesmo problema porque, neste caso, o bit alto está definido.
Blair Conrad
(byte) Short.parseShort (thisByte, 16) resolve esse problema
Jamey Hicks
3

Para o que vale, aqui está outra versão que suporta strings de comprimento ímpar, sem recorrer à concatenação de strings.

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;
}
Conor Svensson
fonte
2

Eu sempre usei um método como

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

esse método divide-se em valores hexadecimais delimitados por espaço, mas não seria difícil dividir a string em outros critérios, como em agrupamentos de dois caracteres.

pfranza
fonte
A concatenação de cadeias é desnecessária. Basta usar Integer.valueOf (val, 16).
Michael Myers
Eu tentei usar as conversões Radix como isso antes e eu tive resultados mistos
pfranza
obrigado - estranhamente funciona bem com esta sequência: "9C001C" ou "001C21" e falha com esta: "9C001C21" Exceção no segmento "main" java.lang.NumberFormatException: para a sequência de entrada: "9C001C21" em java.lang. NumberFormatException.forInputString (Origem desconhecida)
rafraf
(Isso não é mais estranho do que no Byte/ bytecaso: maior conjunto de bits sem levar -)
greybeard
2

Eu gosto da solução Character.digit, mas aqui está como eu a resolvi

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;
}
Kernel Panic
fonte
2

O código apresentado por Bert Regelink simplesmente não funciona. Tente o seguinte:

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);
        }
    }
Sean Coffey
fonte
2
Este é realmente um problema diferente e provavelmente pertence a outro segmento.
Sean Coffey
1

Achei o Kernel Panic a solução mais útil para mim, mas tive problemas se a sequência hexadecimal fosse um número ímpar. resolveu assim:

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

Estou adicionando um número de números hexadecimais a uma matriz, por isso passo a referência à matriz que estou usando e o int que preciso converter e retornar a posição relativa do próximo número hexadecimal. Portanto, a matriz de bytes final tem [0] número de pares hexadecimais, [1] [...] pares hexadecimais e, em seguida, o número de pares ...

Clayton Balabanov
fonte
1

Com base na solução votada pelo op, o seguinte deve ser um pouco mais eficiente:

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

Porque: a conversão inicial em uma matriz char poupa as verificações de comprimento em charAt

Philip Helger
fonte
1

Se você prefere os fluxos Java 8 como seu estilo de codificação, isso pode ser alcançado usando apenas primitivas 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();

Os , 0, s2.size()parâmetros na função concatenar do coletor podem ser omitidos se você não se importar em capturar IOException.

Andy Brown
fonte
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;
}
David V
fonte
0

Minha solução formal:

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

É como a função hex2bin () do PHP, mas no estilo Java.

Exemplo:

String data = new String(hex2bin("6578616d706c65206865782064617461"));
// data value: "example hex data"
Daniel De León
fonte
0

Tarde para a festa, mas eu juntei a resposta acima de DaveL em uma classe com a ação inversa - para o caso de ajudar.

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

E classe de teste 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
fonte
0

Eu sei que este é um tópico muito antigo, mas ainda assim gostaria de acrescentar meu centavo.

Se eu realmente precisar codificar uma simples cadeia hexadecimal para conversor binário, gostaria de fazer o seguinte.

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;
}
Tigre
fonte
0

De longe não é a solução mais limpa. Mas funciona para mim e está bem formatado:

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

A saída:

  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                                               | ?
Moritz Schmidt
fonte
-2

Eu acho que vai fazer isso por você. Eu o juntei de uma função semelhante que retornava os dados como uma string:

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;
}
Bob King
fonte
Primeiro, você não precisa converter a string em maiúsculas. Segundo, é possível acrescentar caracteres diretamente a um StringBuffer, que deve ser muito mais eficiente.
Michael Myers
-2

Para mim, essa foi a solução, HEX = "FF01" e depois dividida em FF (255) e 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
fonte
Esta pergunta foi respondida por um tempo e possui várias boas alternativas; infelizmente, sua resposta não fornece nenhum valor significativamente melhorado neste momento.
rfornal