Eu tenho uma matriz de bytes cheia de números hexadecimais e imprimi-la da maneira mais fácil é inútil, porque há muitos elementos não imprimíveis. O que eu preciso é o código hexadecimal exato na forma de:3a5f771c
Eu tenho uma matriz de bytes cheia de números hexadecimais e imprimi-la da maneira mais fácil é inútil, porque há muitos elementos não imprimíveis. O que eu preciso é o código hexadecimal exato na forma de:3a5f771c
Respostas:
A partir da discussão aqui , e especialmente desta resposta, esta é a função que atualmente uso:
private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(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] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}
Meus próprios benchmarks minúsculos (um milhão de bytes por mil vezes, 256 bytes 10 milhões de vezes) mostraram que era muito mais rápido do que qualquer outra alternativa, cerca da metade do tempo em arrays longos. Comparado à resposta da qual tirei, alternar para operações bit a bit - como sugerido na discussão - reduziu em cerca de 20% o tempo para arrays longos. (Edit: Quando digo que é mais rápido que as alternativas, quero dizer o código alternativo oferecido nas discussões. O desempenho é equivalente ao Commons Codec, que usa código muito semelhante.)
Versão 2k20, com relação às seqüências compactas Java 9:
private static final byte[] HEX_ARRAY = "0123456789ABCDEF".toByteArray();
public static String bytesToHex(byte[] bytes) {
byte[] hexChars = new byte[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars, StandardCharsets.UTF_8);
}
String printHexBinary(byte[])
e byte[] parseHexBinary(String)
. printHexBinary
é, no entanto, muito (2x) mais lento que a função nesta resposta. (Eu verifiquei a fonte; ela usa a stringBuilder
. parseHexBinary
Usa uma matriz.) Na verdade, para a maioria dos propósitos, é rápido o suficiente e você provavelmente já a possui.
printHexBinary
?
javax.xml.bind.DataTypeConverter
está a ser removido a partir de Java 11.
A biblioteca do Apache Commons Codec tem uma classe Hex para fazer exatamente esse tipo de trabalho.
import org.apache.commons.codec.binary.Hex;
String foo = "I am a string";
byte[] bytes = foo.getBytes();
System.out.println( Hex.encodeHexString( bytes ) );
import org.apache.commons.codec.*;
você poderia fazerimport org.apache.commons.codec.binary.Hex;
org.bouncycastle.util.encoders.Hex
String toHexString(byte[] data)
O método javax.xml.bind.DatatypeConverter.printHexBinary()
, parte da Arquitetura Java para Ligação XML (JAXB) , era uma maneira conveniente de converter a byte[]
em uma sequência hexadecimal. A DatatypeConverter
classe também incluiu muitos outros métodos úteis de manipulação de dados.
No Java 8 e versões anteriores, o JAXB fazia parte da biblioteca padrão do Java. Foi preterido no Java 9 e removido com o Java 11 , como parte de um esforço para mover todos os pacotes Java EE para suas próprias bibliotecas. É uma longa história . Agora, javax.xml.bind
não existe, e se você deseja usar o JAXB, que contém DatatypeConverter
, precisará instalar a API JAXB e o JAXB Runtime do Maven.
Exemplo de uso:
byte bytes[] = {(byte)0, (byte)0, (byte)134, (byte)0, (byte)61};
String hex = javax.xml.bind.DatatypeConverter.printHexBinary(bytes);
Vai resultar em:
000086003D
Esta resposta é a mesma que esta .
Solução mais simples, sem bibliotecas externas, sem constantes de dígitos:
public static String byteArrayToHex(byte[] a) {
StringBuilder sb = new StringBuilder(a.length * 2);
for(byte b: a)
sb.append(String.format("%02x", b));
return sb.toString();
}
Uma solução Goiaba, para ser completo:
import com.google.common.io.BaseEncoding;
...
byte[] bytes = "Hello world".getBytes(StandardCharsets.UTF_8);
final String hex = BaseEncoding.base16().lowerCase().encode(bytes);
Agora hex
é "48656c6c6f20776f726c64"
.
new HashCode(bytes).toString()
.
HashCode.fromBytes(checksum).toString()
Este oneliner simples funciona para mim.
String result = new BigInteger(1, inputBytes).toString(16);
EDIT - Usar isso removerá os zeros à esquerda, mas ele trabalhou no meu caso de uso. Obrigado @Voicu por apontar
Aqui estão algumas opções comuns ordenadas de simples (one-liner) a complexas (enorme biblioteca). Se você está interessado em desempenho, consulte os micro benchmarks abaixo.
Uma solução muito simples é usar a BigInteger
representação hexadecimal da:
new BigInteger(1, someByteArray).toString(16)
Observe que, como ele lida com números que não sejam seqüências de bytes arbitrárias , ele omitirá zeros à esquerda - isso pode ou não ser o que você deseja (por exemplo, 000AE3
vs 0AE3
para uma entrada de 3 bytes). Isso também é muito lento, cerca de 100x mais lento em comparação com a próxima opção.
Aqui está um trecho de código completo, com cópia e colável que suporta maiúsculas / minúsculas e endianness . Ele é otimizado para minimizar a complexidade da memória e maximizar o desempenho e deve ser compatível com todas as versões modernas do Java (5+).
private static final char[] LOOKUP_TABLE_LOWER = new char[]{0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66};
private static final char[] LOOKUP_TABLE_UPPER = new char[]{0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46};
public static String encode(byte[] byteArray, boolean upperCase, ByteOrder byteOrder) {
// our output size will be exactly 2x byte-array length
final char[] buffer = new char[byteArray.length * 2];
// choose lower or uppercase lookup table
final char[] lookup = upperCase ? LOOKUP_TABLE_UPPER : LOOKUP_TABLE_LOWER;
int index;
for (int i = 0; i < byteArray.length; i++) {
// for little endian we count from last to first
index = (byteOrder == ByteOrder.BIG_ENDIAN) ? i : byteArray.length - i - 1;
// extract the upper 4 bit and look up char (0-A)
buffer[i << 1] = lookup[(byteArray[index] >> 4) & 0xF];
// extract the lower 4 bit and look up char (0-A)
buffer[(i << 1) + 1] = lookup[(byteArray[index] & 0xF)];
}
return new String(buffer);
}
public static String encode(byte[] byteArray) {
return encode(byteArray, false, ByteOrder.BIG_ENDIAN);
}
O código fonte completo com licença e decodificador Apache v2 pode ser encontrado aqui .
Enquanto trabalhava no meu projeto anterior, criei este pequeno kit de ferramentas para trabalhar com bytes em Java. Não possui dependências externas e é compatível com Java 7+. Inclui, entre outros, um HEX en / decodificador muito rápido e bem testado:
import at.favre.lib.bytes.Bytes;
...
Bytes.wrap(someByteArray).encodeHex()
Você pode conferir no Github: bytes-java .
Claro que existem os bons codecs comuns . ( avisando a opinião adiante ) Enquanto trabalhava no projeto descrito acima, analisei o código e fiquei bastante decepcionado; muitos códigos desorganizados duplicados, codecs obsoletos e exóticos provavelmente só são úteis para muito poucas implementações lentas e bem projetadas e de engenharia de codecs populares (especificamente Base64). Portanto, eu tomaria uma decisão informada se você quiser usá-lo ou como alternativa. De qualquer forma, se você ainda quiser usá-lo, aqui está um trecho de código:
import org.apache.commons.codec.binary.Hex;
...
Hex.encodeHexString(someByteArray));
Mais frequentemente, você já tem o Goiaba como uma dependência. Se sim, basta usar:
import com.google.common.io.BaseEncoding;
...
BaseEncoding.base16().lowerCase().encode(someByteArray);
Se você usar a estrutura do Spring com o Spring Security, poderá usar o seguinte:
import org.springframework.security.crypto.codec.Hex
...
new String(Hex.encode(someByteArray));
Se você já usa a estrutura de segurança Bouncy Castle, pode usar seu Hex
utilitário:
import org.bouncycastle.util.encoders.Hex;
...
Hex.toHexString(someByteArray);
Nas versões anteriores do Java (8 e abaixo), o código Java para JAXB foi incluído como dependência de tempo de execução. Desde a modularização do Java 9 e do Jigsaw, seu código não pode acessar outro código fora do módulo sem declaração explícita. Esteja ciente de que você recebe uma exceção como:
java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
ao executar em uma JVM com Java 9+. Nesse caso, mude as implementações para qualquer uma das alternativas acima. Veja também esta questão .
Aqui estão os resultados de um simples micro benchmark JMH que codifica matrizes de bytes de tamanhos diferentes . Os valores são operações por segundo, portanto, quanto maior, melhor. Observe que os micro benchmarks muitas vezes não representam o comportamento do mundo real, portanto, leve esses resultados com um pouco de sal.
| Name (ops/s) | 16 byte | 32 byte | 128 byte | 0.95 MB |
|----------------------|-----------:|-----------:|----------:|--------:|
| Opt1: BigInteger | 2,088,514 | 1,008,357 | 133,665 | 4 |
| Opt2/3: Bytes Lib | 20,423,170 | 16,049,841 | 6,685,522 | 825 |
| Opt4: Apache Commons | 17,503,857 | 12,382,018 | 4,319,898 | 529 |
| Opt5: Guava | 10,177,925 | 6,937,833 | 2,094,658 | 257 |
| Opt6: Spring | 18,704,986 | 13,643,374 | 4,904,805 | 601 |
| Opt7: BC | 7,501,666 | 3,674,422 | 1,077,236 | 152 |
| Opt8: JAX-B | 13,497,736 | 8,312,834 | 2,590,940 | 346 |
Especificações: JDK 8u202, i7-7700K, Win10, 24 GB de RAM. Veja a referência completa aqui .
Use a classe DataTypeConverterjavax.xml.bind.DataTypeConverter
String hexString = DatatypeConverter.printHexBinary(bytes[] raw);
Eu usaria algo assim para comprimento fixo, como hashes:
md5sum = String.format("%032x", new BigInteger(1, md.digest()));
Encontrei três maneiras diferentes aqui: http://www.rgagnon.com/javadetails/java-0596.html
O mais elegante, como ele também observa, acho que é este:
static final String HEXES = "0123456789ABCDEF";
public static String getHex( byte [] raw ) {
if ( raw == null ) {
return null;
}
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();
}
if (raw == null) return null
não falha rápido. Por que você usaria uma null
chave?
Com o menor custo de armazenamento da tabela de pesquisa, essa implementação é simples e muito rápida.
private static final char[] BYTE2HEX=(
"000102030405060708090A0B0C0D0E0F"+
"101112131415161718191A1B1C1D1E1F"+
"202122232425262728292A2B2C2D2E2F"+
"303132333435363738393A3B3C3D3E3F"+
"404142434445464748494A4B4C4D4E4F"+
"505152535455565758595A5B5C5D5E5F"+
"606162636465666768696A6B6C6D6E6F"+
"707172737475767778797A7B7C7D7E7F"+
"808182838485868788898A8B8C8D8E8F"+
"909192939495969798999A9B9C9D9E9F"+
"A0A1A2A3A4A5A6A7A8A9AAABACADAEAF"+
"B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"+
"C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"+
"D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"+
"E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF"+
"F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF").toCharArray();
;
public static String getHexString(byte[] bytes) {
final int len=bytes.length;
final char[] chars=new char[len<<1];
int hexIndex;
int idx=0;
int ofs=0;
while (ofs<len) {
hexIndex=(bytes[ofs++] & 0xFF)<<1;
chars[idx++]=BYTE2HEX[hexIndex++];
chars[idx++]=BYTE2HEX[hexIndex];
}
return new String(chars);
}
BYTE2HEX
matriz com um for
ciclo simples ?
static { }
bloco.
Que tal agora?
String byteToHex(final byte[] hash)
{
Formatter formatter = new Formatter();
for (byte b : hash)
{
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}
Eu prefiro usar isso:
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes, int offset, int count) {
char[] hexChars = new char[count * 2];
for ( int j = 0; j < count; j++ ) {
int v = bytes[j+offset] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
É uma adaptação um pouco mais flexível da resposta aceita. Pessoalmente, mantenho a resposta aceita e essa sobrecarga, utilizáveis em mais contextos.
Normalmente, uso o seguinte método para a declaração debuf, mas não sei se é a melhor maneira de fazê-lo ou não
private static String digits = "0123456789abcdef";
public static String toHex(byte[] data){
StringBuffer buf = new StringBuffer();
for (int i = 0; i != data.length; i++)
{
int v = data[i] & 0xff;
buf.append(digits.charAt(v >> 4));
buf.append(digits.charAt(v & 0xf));
}
return buf.toString();
}
StringBuilder buf = new StringBuilder(data.length * 2);
.
Ok, então existem várias maneiras de fazer isso, mas se você decidir usar uma biblioteca, sugiro bisbilhotar no seu projeto para ver se algo foi implementado em uma biblioteca que já faz parte do seu projeto antes de adicionar uma nova biblioteca. apenas para fazer isso. Por exemplo, se você ainda não possui
org.apache.commons.codec.binary.Hex
talvez você tenha ...
org.apache.xerces.impl.dv.util.HexBin
Se você estiver usando a estrutura Spring Security, poderá usar:
import org.springframework.security.crypto.codec.Hex
final String testString = "Test String";
final byte[] byteArray = testString.getBytes();
System.out.println(Hex.encode(byteArray));
Adicionar uma jarra de utilidade para uma função simples não é uma boa opção. Em vez disso, monte suas próprias classes de utilitários. é possível uma implementação mais rápida.
public class ByteHex {
public static int hexToByte(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 String[] byteToHexTable = 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"
};
private static final String[] byteToHexTableLowerCase = 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 byteToHexTable[b & 0xFF];
}
public static String byteToHex(byte[] bytes){
if(bytes == null) return null;
StringBuilder sb = new StringBuilder(bytes.length*2);
for(byte b : bytes) sb.append(byteToHexTable[b & 0xFF]);
return sb.toString();
}
public static String byteToHex(short[] bytes){
StringBuilder sb = new StringBuilder(bytes.length*2);
for(short b : bytes) sb.append(byteToHexTable[((byte)b) & 0xFF]);
return sb.toString();
}
public static String byteToHexLowerCase(byte[] bytes){
StringBuilder sb = new StringBuilder(bytes.length*2);
for(byte b : bytes) sb.append(byteToHexTableLowerCase[b & 0xFF]);
return sb.toString();
}
public static byte[] hexToByte(String hexString) {
if(hexString == null) return null;
byte[] byteArray = new byte[hexString.length() / 2];
for (int i = 0; i < hexString.length(); i += 2) {
byteArray[i / 2] = (byte) (hexToByte(hexString.charAt(i)) * 16 + hexToByte(hexString.charAt(i+1)));
}
return byteArray;
}
public static byte hexPairToByte(char ch1, char ch2) {
return (byte) (hexToByte(ch1) * 16 + hexToByte(ch2));
}
}
Uma pequena variante da solução proposta por @maybewecouldstealavan, que permite agrupar visualmente N bytes na sequência hexadecimal de saída:
final static char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
final static char BUNDLE_SEP = ' ';
public static String bytesToHexString(byte[] bytes, int bundleSize /*[bytes]*/]) {
char[] hexChars = new char[(bytes.length * 2) + (bytes.length / bundleSize)];
for (int j = 0, k = 1; j < bytes.length; j++, k++) {
int v = bytes[j] & 0xFF;
int start = (j * 2) + j/bundleSize;
hexChars[start] = HEX_ARRAY[v >>> 4];
hexChars[start + 1] = HEX_ARRAY[v & 0x0F];
if ((k % bundleSize) == 0) {
hexChars[start + 2] = BUNDLE_SEP;
}
}
return new String(hexChars).trim();
}
Isso é:
bytesToHexString("..DOOM..".toCharArray().getBytes(), 2);
2E2E 444F 4F4D 2E2E
bytesToHexString("..DOOM..".toCharArray().getBytes(), 4);
2E2E444F 4F4D2E2E
Não é possível encontrar nesta solução nenhuma solução que não
Aqui está uma solução que não possui as falhas acima (nenhuma promessa é minha, mas não tem outras falhas)
import java.math.BigInteger;
import static java.lang.System.out;
public final class App2 {
// | proposed solution.
public static String encode(byte[] bytes) {
final int length = bytes.length;
// | BigInteger constructor throws if it is given an empty array.
if (length == 0) {
return "00";
}
final int evenLength = (int)(2 * Math.ceil(length / 2.0));
final String format = "%0" + evenLength + "x";
final String result = String.format (format, new BigInteger(bytes));
return result;
}
public static void main(String[] args) throws Exception {
// 00
out.println(encode(new byte[] {}));
// 01
out.println(encode(new byte[] {1}));
//203040
out.println(encode(new byte[] {0x20, 0x30, 0x40}));
// 416c6c20796f75722062617365206172652062656c6f6e6720746f2075732e
out.println(encode("All your base are belong to us.".getBytes()));
}
}
Não consegui obter isso em 62 opcodes, mas se você puder viver sem preenchimento de 0, caso o primeiro byte seja menor que 0x10, a solução a seguir usará apenas 23 opcodes. Realmente mostra como soluções "fáceis de implementar" como "pad com zero se o comprimento da string for ímpar" podem ficar bem caras se uma implementação nativa ainda não estiver disponível (ou, neste caso, se o BigInteger tivesse a opção de prefixar zeros em para sequenciar).
public static String encode(byte[] bytes) {
final int length = bytes.length;
// | BigInteger constructor throws if it is given an empty array.
if (length == 0) {
return "00";
}
return new BigInteger(bytes).toString(16);
}
Minha solução é baseada na solução de maybeWeCouldStealAVan, mas não depende de nenhuma tabela de pesquisa adicionalmente alocada. Ele não usa nenhuma ferramenta de conversão de 'int-to-char' (na verdade Character.forDigit()
, executa algumas comparações para verificar qual é realmente o dígito) e, portanto, pode ser um pouco mais lenta. Por favor, sinta-se livre para usá-lo onde quiser. Felicidades.
public static String bytesToHex(final byte[] bytes)
{
final int numBytes = bytes.length;
final char[] container = new char[numBytes * 2];
for (int i = 0; i < numBytes; i++)
{
final int b = bytes[i] & 0xFF;
container[i * 2] = Character.forDigit(b >>> 4, 0x10);
container[i * 2 + 1] = Character.forDigit(b & 0xF, 0x10);
}
return new String(container);
}
Se você está procurando uma matriz de bytes exatamente como esta para python, eu converti essa implementação Java em python.
class ByteArray:
@classmethod
def char(cls, args=[]):
cls.hexArray = "0123456789ABCDEF".encode('utf-16')
j = 0
length = (cls.hexArray)
if j < length:
v = j & 0xFF
hexChars = [None, None]
hexChars[j * 2] = str( cls.hexArray) + str(v)
hexChars[j * 2 + 1] = str(cls.hexArray) + str(v) + str(0x0F)
# Use if you want...
#hexChars.pop()
return str(hexChars)
array = ByteArray()
print array.char(args=[])
Aqui está uma java.util.Base64
implementação do tipo (parcial), não é bonita?
public class Base16/*a.k.a. Hex*/ {
public static class Encoder{
private static char[] toLowerHex={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
private static char[] toUpperHex={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
private boolean upper;
public Encoder(boolean upper) {
this.upper=upper;
}
public String encode(byte[] data){
char[] value=new char[data.length*2];
char[] toHex=upper?toUpperHex:toLowerHex;
for(int i=0,j=0;i<data.length;i++){
int octet=data[i]&0xFF;
value[j++]=toHex[octet>>4];
value[j++]=toHex[octet&0xF];
}
return new String(value);
}
static final Encoder LOWER=new Encoder(false);
static final Encoder UPPER=new Encoder(true);
}
public static Encoder getEncoder(){
return Encoder.LOWER;
}
public static Encoder getUpperEncoder(){
return Encoder.UPPER;
}
//...
}
private static String bytesToHexString(byte[] bytes, int length) {
if (bytes == null || length == 0) return null;
StringBuilder ret = new StringBuilder(2*length);
for (int i = 0 ; i < length ; i++) {
int b;
b = 0x0f & (bytes[i] >> 4);
ret.append("0123456789abcdef".charAt(b));
b = 0x0f & bytes[i];
ret.append("0123456789abcdef".charAt(b));
}
return ret.toString();
}
Converts bytes data to hex characters
@param bytes byte array to be converted to hex string
@return byte String in hex format
private static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
int v;
for (int j = 0; j < bytes.length; j++) {
v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}
toHexString(...)
método que pode ajudar se é isso que você está procurando. Também éString.format(...)
possível fazer alguns truques de formatação usando a%2x
sequência de códigos.