Eu tenho uma matriz de bytes. Eu quero que cada byte String dessa matriz seja convertida em seus valores hexadecimais correspondentes.
Existe alguma função em Java para converter uma matriz de bytes em hexadecimal?
Eu tenho uma matriz de bytes. Eu quero que cada byte String dessa matriz seja convertida em seus valores hexadecimais correspondentes.
Existe alguma função em Java para converter uma matriz de bytes em hexadecimal?
Respostas:
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
sintaxe
%[flags][width]conversion
'0'
- O resultado será preenchido com zero2
'X'
- o resultado é formatado como um número inteiro hexadecimal, maiúsculoObservando o texto da pergunta, também é possível que seja solicitado:
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]"
Várias respostas aqui usam Integer.toHexString(int)
; isso é possível, mas com algumas ressalvas. Como o parâmetro é um int
, uma conversão primitiva de ampliação é executada no byte
argumento, o que envolve a extensão do sinal.
byte b = -1;
System.out.println(Integer.toHexString(b));
// prints "ffffffff"
O de 8 bits byte
, assinado em Java, é estendido para um sinal de 32 bits int
. Para desfazer efetivamente essa extensão de sinal, é possível mascarar o byte
com 0xFF
.
byte b = -1;
System.out.println(Integer.toHexString(b & 0xFF));
// prints "ff"
Outro problema com o uso toHexString
é que ele não é preenchido com zeros:
byte b = 10;
System.out.println(Integer.toHexString(b & 0xFF));
// prints "a"
Ambos os fatores combinados devem tornar a String.format
solução mais preferível.
byte
, de -128
até 127
, inclusivetoHexString
. Você tem que mascará-lo com & 0xFF
, ou seja, Integer.toHexString(-46 & 0xFF)
é "d2"
.
byte
valor & 0xFF
sempre. a format
solução acima também pode exigir mascaramento, dependendo do que você está usando como argumento.
Estou postando porque nenhuma das respostas existentes explica por que as abordagens funcionam, o que acho realmente importante para esse problema. Em alguns casos, isso faz com que a solução proposta pareça desnecessariamente complicada e sutil. Para ilustrar, fornecerei uma abordagem bastante direta, mas fornecerei um pouco mais de detalhes para ajudar a ilustrar por que funciona.
Primeiro, o que estamos tentando fazer? Queremos converter um valor de byte (ou uma matriz de bytes) em uma string que represente um valor hexadecimal em ASCII. Portanto, o primeiro passo é descobrir exatamente o que é um byte em Java:
O tipo de dados byte é um número inteiro de complemento assinado de dois bits de 8 bits . Tem um valor mínimo de -128 e um valor máximo de 127 (inclusive). O tipo de dados de bytes pode ser útil para economizar memória em matrizes grandes, onde a economia de memória realmente importa. Eles também podem ser usados no lugar de int, onde seus limites ajudam a esclarecer seu código; o fato de o alcance de uma variável ser limitado pode servir como uma forma de documentação.
O que isto significa? Algumas coisas: Primeiro e mais importante, significa que estamos trabalhando com 8 bits . Por exemplo, podemos escrever o número 2 como 0000 0010. No entanto, como é o complemento de dois, escrevemos um 2 negativo como este: 1111 1110. O que também significa é que a conversão para hex é muito simples. Ou seja, você simplesmente converte cada segmento de 4 bits diretamente em hexadecimal. Observe que, para entender os números negativos nesse esquema, primeiro você precisa entender o complemento de dois. Se você ainda não entende o complemento de dois, pode ler uma excelente explicação, aqui: http://www.cs.cornell.edu/~tomf/notes/cps104/twoscomp.html
Quando um número está no complemento de dois, é simples convertê-lo em hexadecimal. Em geral, a conversão de binário em hexadecimal é muito direta e, como você verá nos próximos dois exemplos, é possível ir diretamente do complemento de dois para hexadecimal.
Exemplo 1: Converta 2 em Hex.
1) Primeiro converta 2 para binário no complemento de dois:
2 (base 10) = 0000 0010 (base 2)
2) Agora converta binário em hexadecimal:
0000 = 0x0 in hex
0010 = 0x2 in hex
therefore 2 = 0000 0010 = 0x02.
Exemplo 2: Converta -2 (no complemento de dois) para Hex.
1) Primeiro converta -2 para binário no complemento de dois:
-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) Agora converta para hex:
1111 = 0xF in hex
1110 = 0xE in hex
therefore: -2 = 1111 1110 = 0xFE.
Agora que abordamos o conceito, você descobrirá que podemos alcançar o que queremos com algumas máscaras e mudanças simples. A principal coisa a entender é que o byte que você está tentando converter já está no complemento de dois. Você não faz essa conversão sozinho. Penso que este é um ponto importante de confusão sobre esta questão. Tomemos, por exemplo, a seguinte matriz de bytes:
byte[] bytes = new byte[]{-2,2};
Nós apenas os convertemos manualmente em hexadecimal, acima, mas como podemos fazer isso em Java? Aqui está como:
Etapa 1: Crie um StringBuffer para armazenar nossa computação.
StringBuffer buffer = new StringBuffer();
Etapa 2: isole os bits de ordem superior, converta-os em hexadecimal e adicione-os ao buffer
Dado o número binário 1111 1110, podemos isolar os bits de ordem superior deslocando-os primeiro por 4 e depois zerando o restante do número. Logicamente, isso é simples, no entanto, os detalhes da implementação em Java (e em muitas linguagens) introduzem uma ruga devido à extensão do sinal. Essencialmente, quando você altera um valor de byte, o Java primeiro converte seu valor em um número inteiro e depois executa a extensão do sinal. Portanto, enquanto você esperaria que 1111 1110 >> 4 fosse 0000 1111, na realidade, em Java, ele é representado como o complemento dos dois 0xFFFFFFFF!
Então, voltando ao nosso exemplo:
1111 1110 >> 4 (shift right 4) = 1111 1111 1111 1111 1111 1111 1111 1111 (32 bit sign-extended number in two's complement)
Podemos então isolar os bits com uma máscara:
1111 1111 1111 1111 1111 1111 1111 1111 & 0xF = 0000 0000 0000 0000 0000 0000 0000 1111
therefore: 1111 = 0xF in hex.
Em Java, podemos fazer tudo isso de uma só vez:
Character.forDigit((bytes[0] >> 4) & 0xF, 16);
A função forDigit apenas mapeia o número que você passa para o conjunto de números hexadecimais 0-F.
Etapa 3: Em seguida, precisamos isolar os bits de ordem inferior. Como os bits que queremos já estão na posição correta, podemos apenas mascará-los:
1111 1110 & 0xF = 0000 0000 0000 0000 0000 0000 0000 1110 (recall sign extension from before)
therefore: 1110 = 0xE in hex.
Como antes, em Java, podemos fazer isso de uma só vez:
Character.forDigit((bytes[0] & 0xF), 16);
Juntando tudo isso, podemos fazer isso como um loop for e converter toda a matriz:
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));
}
Esperamos que esta explicação torne as coisas mais claras para aqueles que se perguntam exatamente o que está acontecendo nos muitos exemplos que você encontrará na internet. Espero não ter cometido erros flagrantes, mas sugestões e correções são muito bem-vindas!
Character.digit()
, como(byte) ((Character.digit(str.charAt(0), 16) << 4) + Character.digit(str.charAt(1), 16))
A maneira mais rápida que encontrei para fazer isso é a seguinte:
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();
}
É ~ 50x mais rápido que String.format
. se você quiser testá-lo:
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
}
}
}
Edit : Acabei de encontrar algo apenas um lil mais rápido e que mantém uma linha, mas não é compatível com o JRE 9. Use por sua conta e risco
import javax.xml.bind.DatatypeConverter;
DatatypeConverter.printHexBinary(raw);
printHexBinary
do código-fonte do src.zip do jdk, que parece 1 vez mais rápido que o primeiro método.
Tente desta maneira:
byte bv = 10;
String hexString = Integer.toHexString(bv);
Lidando com array (se entendi corretamente):
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();
Como os poligenelubrificantes mencionados, String.format()
é a resposta certa em comparação com Integer.toHexString()
(uma vez que lida com números negativos da maneira correta).
-1
.
bv
disso, retorna um único caractere hexadecimal . Enquanto o restante do código retorna uma sequência de caracteres hexadecimais . Alterei o código com o delímetro para que você possa entender agora.
Integer.toHexString
se mascarar o byte
com 0xFF
para desfazer a extensão do sinal.
A melhor solução é esse one-liner durão:
String hex=DatatypeConverter.printHexBinary(byte[] b);
como mencionado aqui
new BigInteger(byteArray).toString(16)
é o caminho a seguir então. São problemas de perf com isso ??
Se você deseja uma representação hexadecimal de largura constante, ou seja, 0A
vez de A
, para recuperar os bytes sem ambiguidade, tente format()
:
StringBuilder result = new StringBuilder();
for (byte bb : byteArray) {
result.append(String.format("%02X", bb));
}
return result.toString();
Uma maneira curta e simples de converter byte[]
em sequência hexadecimal usando 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
A classe de java.math.BigInteger
classe do sistema interna ( java.math.BigInteger ) é compatível com dados binários e hexadecimais:
BigInteger(signum=1, byte[])
para criar um grande número inteiro byte[]
(defina seu primeiro parâmetrosignum
= 1
para manipular corretamente os bytes negativos)BigInteger.toString(16)
para converter o número inteiro grande em sequência hexadecimalnew BigInteger("ffa74b", 16)
- não lida corretamente com o zero inicialSe você quiser ter o zero inicial no resultado hexadecimal, verifique seu tamanho e adicione o zero ausente, se necessário:
if (hex.length() % 2 == 1)
hex = "0" + hex;
Use new BigInteger(1, bytes)
, em vez de new BigInteger(bytes)
, porque Java é " quebrado por design " e o byte
tipo de dados não contém bytes, mas assinou números inteiros minúsculos [-128 ... 127]. Se o primeiro byte for negativo, BigInteger
assume-se que você passa um número inteiro grande negativo. Apenas passe 1
como primeiro parâmetro ( signum=1
).
A conversão de hex para hexbyte[]
é complicada: às vezes um zero inicial entra na saída produzida e deve ser limpo assim:
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;
}
A última nota é se o byte[]
tiver vários zeros à esquerda, eles serão perdidos.
Se você está feliz em usar uma biblioteca externa, a org.apache.commons.codec.binary.Hex
classe possui um encodeHex
método que pega byte[]
ae retorna a char[]
. Este método é MUITO mais rápido que a opção de formato e encapsula os detalhes da conversão. Também vem com um decodeHex
método para a conversão oposta.
javax
espaço para nome nem sempre está disponível.
Você pode usar o método da biblioteca Bouncy Castle Provider :
org.bouncycastle.util.encoders.Hex.toHexString(byteArray);
O pacote Bouncy Castle Crypto é uma implementação Java de algoritmos criptográficos. Este jar contém o provedor JCE e a API leve para as APIs de criptografia de castelo insuflável para JDK 1.5 a JDK 1.8.
Dependência do Maven:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.60</version>
</dependency>
ou do Apache Commons Codec :
org.apache.commons.codec.binary.Hex.encodeHexString(byteArray);
O pacote do Apache Commons Codec contém codificadores e decodificadores simples para vários formatos, como Base64 e Hexadecimal. Além desses codificadores e decodificadores amplamente utilizados, o pacote de codecs também mantém uma coleção de utilitários de codificação fonética.
Dependência do Maven:
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
</dependency>
Este é o código que eu encontrei para executar o mais rápido até agora. Eu o executei em matrizes de 109015 bytes de comprimento 32, em 23ms. Eu estava executando-o em uma VM, por isso provavelmente será executado mais rapidamente em bare metal.
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;
}
Então você pode simplesmente fazer
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)
retorna"-fdfcfbfb"
(int) 255
) desde que os bytes Java são assinados, portanto o resultado deve ser FF02030405
. Se você experimentar a solução @Jerinaw acima, verá que ela imprimirá a saída correta. Veja também a solução de Svetlin Nakov abaixo.
Aqui está uma função simples para converter bytes em hexadecimal
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();
}
Outros abordaram o caso geral. Mas se você tiver uma matriz de bytes de um formulário conhecido, por exemplo, um endereço MAC, poderá:
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]);
Criando (e destruindo) um monte de String
instâncias não é uma boa maneira se o desempenho for um problema.
Por favor, ignore os argumentos detalhados (duplicados) que verificam as declarações if
. Isso é para (outros) propósitos educacionais.
Projeto completo: http://jinahya.googlecode.com/svn/trunk/com.googlecode.jinahya/hex-codec/
Codificação...
/**
* 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);
}
Decodificando ...
/**
* 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);
}
Esta é uma maneira muito rápida. Nenhuma biblioteca externa necessária.
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);
}
Eu não conseguia entender exatamente o que você queria dizer com byte String, mas aqui estão algumas conversões de byte para String e vice-versa, é claro que há muito mais nas documentações oficiais
Integer intValue = 149;
O valor do byte correspondente é:
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
recupere o valor inteiro de uma variável Byte:
Integer anInt = byteValue.intValue(); // This will convert the byteValue variable to a signed Integer
De Byte e Inteiro a Hex String:
É assim que eu faço:
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
Convertendo uma matriz de bytes em uma sequência hexadecimal:
Até onde eu sei, não existe uma função simples para converter todos os elementos dentro de uma matriz de alguns Object
em elementos de outra Object
, então você deve fazer isso sozinho. Você pode usar as seguintes funções:
De byte [] a String:
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;
}
E da cadeia hexadecimal ao byte []:
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;
}
É tarde demais, mas espero que isso ajude outros;)
Aqui está o seu método rápido:
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];
}
Assim como algumas outras respostas, eu recomendo usar String.format()
e BigInteger
. Mas, para interpretar a matriz de bytes como representação binária big-endian em vez de representação binária de complemento de dois (com signum e uso incompleto do intervalo de valores hexadecimais possíveis), use BigInteger (int signum, byte [] magnitude) , não BigInteger (byte [] val ) .
Por exemplo, para uma matriz de bytes de comprimento 8, use:
String.format("%016X", new BigInteger(1,bytes))
Vantagens:
Desvantagem:
Exemplo:
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();
}
Exemplo de saída:
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