HOWTO · Java
Converter Byte Array em Integer em Java
Este tutorial demonstra como converter array de bytes em int em Java
Nesta página
Converter um array de bytes em um inteiro em Java é uma tarefa comum ao lidar com protocolos de rede, E/S de arquivos ou formatos de dados binários. A abordagem correta depende do que os bytes representam: às vezes vários bytes codificam um único int, e às vezes cada byte é um valor independente. Este artigo cobre os métodos do núcleo do Java — ByteBuffer, DataInputStream, deslocamento manual de bits e BigInteger — além das regras de ordem de bytes e de sinal que determinam se o resultado está correto.
Converter quatro bytes em um int com ByteBuffer
O ByteBuffer (em java.nio) é a ferramenta mais direta do núcleo do Java para essa conversão. O método wrap cria um buffer que compartilha o armazenamento do array, e getInt() lê quatro bytes a partir da posição atual do buffer e os interpreta como um único int. Execute este exemplo:
Os rótulos exibidos pelos exemplos de código e saída desta seção permanecem em inglês.
import java.nio.ByteBuffer;
public class ByteArrayToInt {
public static void main(String[] args) {
byte[] byteArray = {0x00, 0x01, 0x03, 0x10};
int intValue = ByteBuffer.wrap(byteArray).getInt();
System.out.println("Converted Integer Value: " + intValue);
}
}
Saída:
Converted Integer Value: 66320
Um ByteBuffer é big-endian por padrão em qualquer plataforma: o primeiro byte do array é tratado como o byte mais significativo. Se os dados foram gravados em ordem little-endian, selecione essa ordem explicitamente com ByteOrder antes de ler:
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class ByteArrayToIntOrder {
public static void main(String[] args) {
byte[] byteArray = {0x00, 0x01, 0x03, 0x10};
int bigEndianValue = ByteBuffer.wrap(byteArray).getInt();
int littleEndianValue =
ByteBuffer.wrap(byteArray).order(ByteOrder.LITTLE_ENDIAN).getInt();
System.out.println("big-endian: " + bigEndianValue);
System.out.println("little-endian: " + littleEndianValue);
}
}
Saída:
big-endian: 66320
little-endian: 268632320
Dois detalhes são importantes aqui. Primeiro, getInt() lê a partir da posição atual do buffer e a avança em quatro posições, portanto chamá-lo duas vezes no mesmo buffer lê os quatro bytes seguintes; um novo wrap sempre começa na posição 0. Segundo, quando restam menos de quatro bytes, getInt() lança um BufferUnderflowException, então verifique o comprimento da entrada antes de ler.
Ler quatro bytes com DataInputStream
Quando os bytes chegam por meio de um stream — ou quando você precisa ler vários valores primitivos em sequência — o DataInputStream é uma boa opção. Encapsule o array em um ByteArrayInputStream, encapsule esse em um DataInputStream e chame readInt():
Os rótulos exibidos pelos exemplos de código e saída desta seção permanecem em inglês.
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
public class ByteArrayToIntWithDataInputStream {
public static void main(String[] args) throws IOException {
byte[] byteArray = {0x00, 0x01, 0x03, 0x10};
try (DataInputStream input =
new DataInputStream(new ByteArrayInputStream(byteArray))) {
int intValue = input.readInt();
System.out.println("Converted Integer Value: " + intValue);
}
}
}
Saída:
Converted Integer Value: 66320
O readInt() sempre interpreta os próximos quatro bytes em ordem big-endian, independentemente da plataforma. Quando restam menos de quatro bytes no stream, ele lança um EOFException, que você pode capturar para relatar uma entrada curta em vez de deixar o programa falhar:
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
public class ByteArrayToIntShortInput {
public static void main(String[] args) throws IOException {
byte[] byteArray = {0x03, 0x10};
try (DataInputStream input =
new DataInputStream(new ByteArrayInputStream(byteArray))) {
int intValue = input.readInt();
System.out.println("Converted Integer Value: " + intValue);
} catch (EOFException e) {
System.out.println("readInt() needs four bytes, but only " + byteArray.length + " remain");
}
}
}
Saída:
readInt() needs four bytes, but only 2 remain
Construir um int deslocando bytes
Deslocar os bytes manualmente mostra exatamente como a conversão funciona e dá controle total sobre a ordem e o comprimento. Para cada byte, desloque o valor acumulado 8 bits à esquerda e combine o próximo byte com OR:
Os rótulos exibidos pelos exemplos de código e saída desta seção permanecem em inglês.
public class ByteArrayToIntManually {
public static void main(String[] args) {
byte[] byteArray = {0x00, 0x01, 0x03, 0x10};
int intValue = 0;
for (byte b : byteArray) {
intValue = (intValue << 8) | (b & 0xFF);
}
System.out.println("Converted Integer Value: " + intValue);
}
}
Saída:
Converted Integer Value: 66320
A máscara b & 0xFF é necessária porque o tipo byte do Java tem sinal: 0x80 é armazenado como -128. Sem a máscara, | combinaria 0xFFFFFF80 em vez de 0x00000080, corrompendo todos os bytes mais altos. Este laço monta os bytes em ordem big-endian — o primeiro elemento do array é o byte mais significativo — e pressupõe que o array contém exatamente quatro bytes. Para uma ordem diferente, percorra o array na direção oposta; para mais bytes, acumule em um long em vez de um int.
Interpretar um array de bytes com BigInteger
O BigInteger aceita um array de bytes diretamente em seu construtor e o interpreta como um número com sinal, big-endian, em complemento de dois, de comprimento arbitrário. O intValue() então reduz o resultado para um int:
Os rótulos exibidos pelos exemplos de código e saída desta seção permanecem em inglês.
import java.math.BigInteger;
public class ByteArrayToIntWithBigInteger {
public static void main(String[] args) {
byte[] byteArray = {0x00, 0x01, 0x03, 0x10};
int intValue = new BigInteger(byteArray).intValue();
System.out.println("Converted Integer Value: " + intValue);
}
}
Saída:
Converted Integer Value: 66320
Como a interpretação tem sinal, um bit inicial 1 produz um valor abaixo de 0; passe um signum de 1 como primeiro argumento do construtor para obter a interpretação sem sinal. Lembre-se de que intValue() mantém apenas os 32 bits mais baixos — ele trunca silenciosamente os valores que não cabem em um int:
import java.math.BigInteger;
public class BigIntegerSignAndRange {
public static void main(String[] args) {
byte[] allOnes = {(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF};
System.out.println("signed: " + new BigInteger(allOnes));
System.out.println("unsigned: " + new BigInteger(1, allOnes));
System.out.println("narrowed to int: " + new BigInteger(1, allOnes).intValue());
}
}
Saída:
signed: -1
unsigned: 4294967295
narrowed to int: -1
O BigInteger é a escolha natural quando o array tem mais de quatro bytes ou quando você precisa da magnitude sem sinal antes da redução.
Converter cada byte separadamente
Todos os métodos acima combinam vários bytes em um único número. Se cada byte é um valor independente — leituras de sensores, canais de cor, campos de protocolo — converta os elementos individualmente. Observe a distinção: getShort() ou readShort() sobre dois bytes produz um único short combinado; isso não converte cada byte separadamente.
Lembre-se também de que o tipo byte do Java tem sinal e varia de -128 a 127. Quando a intenção é um valor sem sinal de 0 a 255, use Byte.toUnsignedInt (disponível desde o Java 8) ou a máscara equivalente b & 0xFF:
Os rótulos exibidos pelos exemplos de código e saída desta seção permanecem em inglês.
public class PrintEachByte {
public static void main(String[] args) {
byte[] byteArray = {0x03, 0x04, (byte) 0x80, (byte) 0xFF};
for (byte b : byteArray) {
System.out.println("signed: " + b + " unsigned: " + Byte.toUnsignedInt(b));
}
}
}
Saída:
signed: 3 unsigned: 3
signed: 4 unsigned: 4
signed: -128 unsigned: 128
signed: -1 unsigned: 255
Escolher um método e tratar casos extremos
Cada abordagem se encaixa em uma situação diferente:
ByteBufferé a primeira escolha para ler umintde quatro bytes de um array: é compacto, suporta ambas as ordens de bytes por meio deByteOrdere fornecegetLong(),getShort()e afins para outros tamanhos.DataInputStreamserve para código que já trabalha com streams e precisa ler vários valores tipados em sequência; suas leituras são sempre big-endian.- O deslocamento manual custa algumas linhas a mais, mas controla a ordem, a posição inicial e a largura com precisão e não precisa de nenhum objeto de buffer ou de stream.
BigIntegerlida com arrays maiores que quatro bytes e com a interpretação explícita com ou sem sinal antes da redução.- A conversão byte a byte com
Byte.toUnsignedIntse aplica quando cada elemento é um valor próprio, e não parte de um único número.
Qualquer que seja o método escolhido, verifique estes pontos antes de converter:
- Comprimento da entrada: uma leitura de quatro bytes em um array mais curto falha —
BufferUnderflowExceptionparaByteBuffer,EOFExceptionparaDataInputStream, e umArrayIndexOutOfBoundsExceptionou um resultado silenciosamente errado para o código manual. - Ordem dos bytes: a ordem do leitor deve corresponder à ordem em que os bytes foram gravados;
ByteBufferusa big-endian por padrão e pode ser trocado comByteOrder, enquanto as leituras deDataInputStreamsão sempre big-endian, sem opção de ordem. - Sinal e faixa:
getInt()ereadInt()retornam umintcom sinal, portanto um valor de 32 bits sem sinal acima deInteger.MAX_VALUEaparece abaixo de 0. UseInteger.toUnsignedLong(intValue)ou acumule em umlongquando os dados de origem forem sem sinal. - Posição do buffer: reutilizar um
ByteBuffercontinua a partir de sua posição atual, não do início; chamerewind()ouwrapnovamente para reler o array.