Java inteiro para matriz de bytes


190

Eu tenho um número inteiro: 1695609641

quando eu uso o método:

String hex = Integer.toHexString(1695609641);
system.out.println(hex); 

dá:

6510f329

mas eu quero uma matriz de bytes:

byte[] bytearray = new byte[] { (byte) 0x65, (byte)0x10, (byte)0xf3, (byte)0x29};

Como posso fazer isso?



Respostas:


293

O uso do ByteBuffer do Java NIO é muito simples:

byte[] bytes = ByteBuffer.allocate(4).putInt(1695609641).array();

for (byte b : bytes) {
   System.out.format("0x%x ", b);
}

resultado:

0x65 0x10 0xf3 0x29 

4
Ou use o formato "0x%02X"se você sempre quiser dois caracteres hexadecimais e hexadecimais em maiúsculas, por exemplo, System.out.format("0x%02X", (byte) 10)displays 0x0A.
Maarten Bodewes

12
Você pode usar Integer.SIZE / 8 para evitar codificar o 4, que é um padrão que funciona bem para outros tipos como Long.
Davidpcj

3
@davenpcj Você pode usar o Integer.SIZE / Byte.SIZE #
rkosegi

11
@rkosegi Ou mesmo Integer.BYTES desde o Java 8 :) #
drvdijk 15/15/15

1
Fio @MaartenBodewes não tem nada a formatação visível, mas a operação tipo nativo
Jacek Cz

146

E se:

public static final byte[] intToByteArray(int value) {
    return new byte[] {
            (byte)(value >>> 24),
            (byte)(value >>> 16),
            (byte)(value >>> 8),
            (byte)value};
}

A ideia não é minha . Eu tirei isso de algum post no dzone.com .


44
Entendo o seu ponto, mas para esta tarefa em particular, o código 'my' é mais declarativo e claro do que algum ByteBuffer 'mágico', que é preciso verificar para ver o que ele faz.
Grzegorz Oledzki 02/02/10

24
@ Kevin - isso é muito duro - existem muitos casos em que esse tipo de código é apropriado, por exemplo, no processamento de imagens. As bibliotecas JDK são ótimas em geral, mas não cobrem e / ou não são otimizadas para todos os casos de uso.
precisa saber é o seguinte

14
acordado; a sobrecarga e a complexidade do ByteBuffer podem não ser apropriadas em comparação com algumas operações de bytes simples e bem conhecidas.
swdunlop 3/11/11

6
Outro ponto que eu acrescentaria é que você usou o operador de mudança à direita não assinado >>> em vez do operador de mudança à direita >>( docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html ), para que o comportamento não seja o desejado / como esperado com assinado vs números não assinados
RobV

4
Essa abordagem parece ser um pouco mais rápida que os métodos ByteBuffer ou BigInteger mencionados. Outra coisa a ter em conta se você estiver fazendo muitas conversões.
candidato

45

BigInteger.valueOf(1695609641).toByteArray()


2
que garantia você tem que produzirá uma matriz de 4 bytes?
MeBigFatGuy

2
Exatamente o que MeBigFatGuy escreveu. Javadoc de BigInteger.toByteArray()states: "A matriz conterá o número mínimo de bytes necessários para representar este BigInteger ..."
icza

2
Onde na pergunta ele solicita que a matriz de bytes tenha um comprimento fixo 4? Dependendo algoritmo este pretende ser parte de você pode utilizar o comprimento da matriz
vmpn

isso é muito mais dinâmico e deve ser a resposta certa. Você pode simplesmente acrescentar uma matriz para criar o tamanho desejado, se quiser. Especialmente quando você precisa considerar valores int assinados em Java.
Droid Chris

2
Isso parece criar um byte para 0x7f e dois bytes para 0x80 (sendo os dois bytes: 0x0 0x80).
Scot

26
byte[] IntToByteArray( int data ) {    
    byte[] result = new byte[4];
    result[0] = (byte) ((data & 0xFF000000) >> 24);
    result[1] = (byte) ((data & 0x00FF0000) >> 16);
    result[2] = (byte) ((data & 0x0000FF00) >> 8);
    result[3] = (byte) ((data & 0x000000FF) >> 0);
    return result;        
}


7
byte[] conv = new byte[4];
conv[3] = (byte) input & 0xff;
input >>= 8;
conv[2] = (byte) input & 0xff;
input >>= 8;
conv[1] = (byte) input & 0xff;
input >>= 8;
conv[0] = (byte) input;

2
Isso extrai os 8 bytes menos significativos. Também evita arrastar o sinal do número de entrada para o octeto convertido.
Carl Smotricz

stackoverflow.com/questions/35305634/… - você pode resolver esse c # em Java?

5
public static byte[] intToBytes(int x) throws IOException {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    DataOutputStream out = new DataOutputStream(bos);
    out.writeInt(x);
    out.close();
    byte[] int_bytes = bos.toByteArray();
    bos.close();
    return int_bytes;
}

4

Os blocos abaixo funcionam pelo menos para enviar um int pelo UDP.

int para byte da matriz:

public byte[] intToBytes(int my_int) throws IOException {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutput out = new ObjectOutputStream(bos);
    out.writeInt(my_int);
    out.close();
    byte[] int_bytes = bos.toByteArray();
    bos.close();
    return int_bytes;
}

matriz de bytes para int:

public int bytesToInt(byte[] int_bytes) throws IOException {
    ByteArrayInputStream bis = new ByteArrayInputStream(int_bytes);
    ObjectInputStream ois = new ObjectInputStream(bis);
    int my_int = ois.readInt();
    ois.close();
    return my_int;
}

4
o uso de ObjectOutputStream está incorreto. Use DataOutputStream, o uso de OOS faz com que a matriz de bytes não tenha 4 bytes.
MeBigFatGuy

2

Como geralmente você deseja converter essa matriz em um int posteriormente, aqui estão os métodos para converter uma matriz de entradas em uma matriz de bytes e vice-versa:

public static byte[] convertToByteArray(final int[] pIntArray)
{
    final byte[] array = new byte[pIntArray.length * 4];
    for (int j = 0; j < pIntArray.length; j++)
    {
        final int c = pIntArray[j];
        array[j * 4] = (byte)((c & 0xFF000000) >> 24);
        array[j * 4 + 1] = (byte)((c & 0xFF0000) >> 16);
        array[j * 4 + 2] = (byte)((c & 0xFF00) >> 8);
        array[j * 4 + 3] = (byte)(c & 0xFF);
    }
    return array;
}

public static int[] convertToIntArray(final byte[] pByteArray)
{
    final int[] array = new int[pByteArray.length / 4];
    for (int i = 0; i < array.length; i++)
        array[i] = (((int)(pByteArray[i * 4]) << 24) & 0xFF000000) |
                (((int)(pByteArray[i * 4 + 1]) << 16) & 0xFF0000) |
                (((int)(pByteArray[i * 4 + 2]) << 8) & 0xFF00) |
                ((int)(pByteArray[i * 4 + 3]) & 0xFF);
    return array;
}

Observe que, devido à propagação do sinal, é necessário o "& 0xFF ..." ao converter de volta para o int.


1
integer & 0xFF

para o primeiro byte

(integer >> 8) & 0xFF

para o segundo e loop etc., escrevendo em uma matriz de bytes pré-alocada. Um pouco bagunçado, infelizmente.


1

A classe org.apache.hadoop.hbase.util.Bytes possui vários métodos úteis de conversão de bytes [], mas talvez você não queira adicionar todo o jar do HBase ao seu projeto apenas para esse fim. É surpreendente que não apenas esse método esteja ausente do AFAIK do JDK, mas também de bibliotecas óbvias como commons io.


1

Minha tentativa:

public static byte[] toBytes(final int intVal, final int... intArray) {
    if (intArray == null || (intArray.length == 0)) {
        return ByteBuffer.allocate(4).putInt(intVal).array();
    } else {
        final ByteBuffer bb = ByteBuffer.allocate(4 + (intArray.length * 4)).putInt(intVal);
        for (final int val : intArray) {
            bb.putInt(val);
        }
        return bb.array();
    }
}

Com ele você pode fazer isso:

byte[] fourBytes = toBytes(0x01020304);
byte[] eightBytes = toBytes(0x01020304, 0x05060708);

A turma completa está aqui: https://gist.github.com/superbob/6548493 , suporta inicialização de curtos ou longos

byte[] eightBytesAgain = toBytes(0x0102030405060708L);

1

Se você estiver usando apache-commons

public static byte[] toByteArray(int value) {
    byte result[] = new byte[4];
    return Conversion.intToByteArray(value, 0, result, 0, 4);
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.