Converter número inteiro em matriz de bytes (Java)

137

o que é uma maneira rápida de converter um Integerem um Byte Array?

por exemplo 0xAABBCCDD => {AA, BB, CC, DD}

Buttercup
fonte
1
Importa qual o formato da matriz de bytes resultante? O que você vai fazer com isso?
22410 skaffman

Respostas:

237

Dê uma olhada na classe ByteBuffer .

ByteBuffer b = ByteBuffer.allocate(4);
//b.order(ByteOrder.BIG_ENDIAN); // optional, the initial order of a byte buffer is always BIG_ENDIAN.
b.putInt(0xAABBCCDD);

byte[] result = b.array();

Definir os garante ordem de bytes que result[0] == 0xAA, result[1] == 0xBB, result[2] == 0xCCe result[3] == 0xDD.

Ou, como alternativa, você pode fazer isso manualmente:

byte[] toBytes(int i)
{
  byte[] result = new byte[4];

  result[0] = (byte) (i >> 24);
  result[1] = (byte) (i >> 16);
  result[2] = (byte) (i >> 8);
  result[3] = (byte) (i /*>> 0*/);

  return result;
}

A ByteBufferaula foi projetada para tarefas com mãos sujas. De fato, o privado java.nio.Bitsdefine esses métodos auxiliares que são usados ​​por ByteBuffer.putInt():

private static byte int3(int x) { return (byte)(x >> 24); }
private static byte int2(int x) { return (byte)(x >> 16); }
private static byte int1(int x) { return (byte)(x >>  8); }
private static byte int0(int x) { return (byte)(x >>  0); }
Gregory Pakosz
fonte
3
isso funcionaria bem se o bytebuffer já estivesse lá ... caso contrário, parece que levaria mais tempo para fazer a alocação, do que apenas alocar uma matriz de bytes de comprimento 4 e fazer a alteração manualmente ... mas provavelmente estamos falando sobre pequenas diferenças.
21713 Jason Jason S
A instância ByteBuffer pode ser armazenada em cache; e internamente é certamente implementado com mudanças e máscaras de qualquer maneira.
Gregory Pakosz 20/12/2009
4
Esta é uma resposta perfeitamente bem. Observe que big-endian é o padrão especificado, e os métodos são "encadeados" e o argumento de posição é opcional, portanto tudo se reduz a: byte [] result = ByteBuffer.allocate (4) .putInt (0xAABBCCDD) .array ( ); Obviamente, se você estiver fazendo isso repetidamente e concatenando todos os resultados juntos (o que é comum quando você está fazendo esse tipo de coisa), aloque um único buffer e coloque repetidamente oFofo () todas as coisas necessárias - ele acompanhará o deslocamento à medida que avança. É realmente uma aula tremendamente útil.
Kevin Bourrillion
o que traz tipos assinados?
Gregory Pakosz
3
Para quem não sabe. O putInt sempre escreverá 4 bytes, independentemente do tamanho do número inteiro de entrada. Se você quiser apenas 2 bytes, use putShort, etc ...
bvdb
36

Usando BigInteger:

private byte[] bigIntToByteArray( final int i ) {
    BigInteger bigInt = BigInteger.valueOf(i);      
    return bigInt.toByteArray();
}

Usando DataOutputStream:

private byte[] intToByteArray ( final int i ) throws IOException {      
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    DataOutputStream dos = new DataOutputStream(bos);
    dos.writeInt(i);
    dos.flush();
    return bos.toByteArray();
}

Usando ByteBuffer:

public byte[] intToBytes( final int i ) {
    ByteBuffer bb = ByteBuffer.allocate(4); 
    bb.putInt(i); 
    return bb.array();
}
Pascal Thivent
fonte
5
preste atenção à ordem dos bytes embora
Gregory Pakosz 20/12/2009
1
O ByteBuffer fornece um int não assinado?
Arun George
@ Pascal Usando ByteBuffer Eu tentei com ByteBuffer bb = ByteBuffer.allocate (3); Para isso, está dando java.nio.BufferOverflowException, não estou entendendo por que não está funcionando com valor menor que 4? Você pode explicar, por favor?
precisa saber é o seguinte
@SanjayJain Você recebe uma exceção de buffer overflow porque as entradas em Java têm tamanho de 32 bits ou 4 bytes e, portanto, exigem que você aloque pelo menos 4 bytes de memória no ByteBuffer.
chocante
@GregoryPakosz está certo sobre a ordem de bytes. Sua resposta usando ByteBufferé mais intuitivo se você está lidando com uma maior int que 2 ^ 31 - 1.
ordonezalex
31

use esta função que funciona para mim

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

traduz o int em um valor de byte

daz
fonte
Também não vale nada que isso funcione, independentemente do bit mais significativo e mais eficiente em comparação com as outras respostas. Também pode usar '>>'.
algolicious
1
Uma solução direta como essa é certamente mais rápida do que chamar qualquer método de biblioteca. Às vezes, você só precisa mexer nos bits diretamente com algumas linhas de código, em vez de incorrer em toda a sobrecarga extra de chamadas de método de biblioteca.
David R Tribble
E isso converte bem entre idiomas, portanto, é bom para o desenvolvimento de software em vários idiomas.
O coordenador
15

Se você gosta de Guava , pode usar sua Intsclasse:


Para intbyte[], use toByteArray():

byte[] byteArray = Ints.toByteArray(0xAABBCCDD);

Resultado é {0xAA, 0xBB, 0xCC, 0xDD}.


O seu reverso é fromByteArray()ou fromBytes():

int intValue = Ints.fromByteArray(new byte[]{(byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD});
int intValue = Ints.fromBytes((byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD);

Resultado é 0xAABBCCDD.

Pang
fonte
8

Você pode usar BigInteger:

De Inteiros:

byte[] array = BigInteger.valueOf(0xAABBCCDD).toByteArray();
System.out.println(Arrays.toString(array))
// --> {-86, -69, -52, -35 }

A matriz retornada é do tamanho necessário para representar o número; portanto, pode ser do tamanho 1, para representar 1, por exemplo. No entanto, o tamanho não pode ser superior a quatro bytes se um int for passado.

From Strings:

BigInteger v = new BigInteger("AABBCCDD", 16);
byte[] array = v.toByteArray();

No entanto, você deve ter cuidado, se o primeiro byte for maior 0x7F(como neste caso), em que o BigInteger inserirá um byte 0x00 no início da matriz. Isso é necessário para distinguir entre valores positivos e negativos.

notnoop
fonte
obrigado! Mas, como esse é o BigInteger, as ints serão agrupadas corretamente? Ou seja, números inteiros que estão fora do Integer.MAX_VALUE, mas ainda podem ser representados com apenas 4 bytes?
Buttercup
1
Isso certamente não é rápido de executar. ;)
Peter Lawrey
Esta não é uma boa opção. Além de adicionar 0x00 byte, também pode remover zeros à esquerda.
ZZ Coder
1

Solução simples que lida adequadamente com o ByteOrder:

ByteBuffer.allocate(4).order(ByteOrder.nativeOrder()).putInt(yourInt).array();

helmy
fonte
1

muito fácil com android

int i=10000;
byte b1=(byte)Color.alpha(i);
byte b2=(byte)Color.red(i);
byte b3=(byte)Color.green(i);
byte b4=(byte)Color.blue(i);
Mukesh Bambhaniya
fonte
1

Isso irá ajudá-lo.

import java.nio.ByteBuffer;
import java.util.Arrays;

public class MyClass
{
    public static void main(String args[]) {
        byte [] hbhbytes = ByteBuffer.allocate(4).putInt(16666666).array();

        System.out.println(Arrays.toString(hbhbytes));
    }
}
wai
fonte
0

Também pode mudar -

byte[] ba = new byte[4];
int val = Integer.MAX_VALUE;

for(byte i=0;i<4;i++)
    ba[i] = (byte)(val >> i*8);
    //ba[3-i] = (byte)(val >> i*8); //Big-endian
Matt
fonte
0

Aqui está um método que deve fazer o trabalho da maneira certa.

public byte[] toByteArray(int value)
{
    final byte[] destination = new byte[Integer.BYTES];
    for(int index = Integer.BYTES - 1; index >= 0; index--)
    {
        destination[i] = (byte) value;
        value = value >> 8;
    };
    return destination;
};
user3424779
fonte
0

É a minha solução:

public void getBytes(int val) {
    byte[] bytes = new byte[Integer.BYTES];
    for (int i = 0;i < bytes.length; i ++) {
        int j = val % Byte.MAX_VALUE;
        bytes[i] = (j == 0 ? Byte.MAX_VALUE : j);
    }
}

Também Stringmétodo y:

public void getBytes(int val) {
    String hex = Integer.toHexString(val);
    byte[] val = new byte[hex.length()/2]; // because byte is 2 hex chars
    for (int i = 0; i < hex.length(); i+=2)
        val[i] = Byte.parseByte("0x" + hex.substring(i, i+2), 16);
    return val;
}
Muskovets
fonte