Does Java ler inteiros em little endian ou big endian?
-
21-08-2019 - |
Pergunta
Eu pergunto porque eu estou enviando um fluxo de bytes de um processo de C para Java. No lado do C o número inteiro de 32 bit tem o bit menos significativo é o primeiro byte e MSB é o quarto byte.
Então, minha pergunta é: No lado do Java quando lemos o byte como foi enviado a partir do processo C, o que é endian no lado do Java?
A follow-up questão: Se o endian no lado do Java não é o mesmo que o enviado, como posso converter entre eles
?Solução
Use a ordem de bytes da rede (big endian), que é o mesmo que Java usa de qualquer maneira. Veja homem htons para os diferentes tradutores em C.
Outras dicas
Eu tropecei aqui via Google e tenho a minha resposta de que Java é grande endian.
Leitura através das respostas que eu gostaria de salientar que bytes têm de fato uma ordem endian, embora felizmente, se você lidou apenas com microprocessadores "mainstream" é improvável que você já encontrei-o como Intel, Motorola, e Zilog todos concordaram com a direção de desvio de seus chips UART e que MSB de um byte seria 2 ** 7 e LSB seria 2 ** 0 em suas CPUs (eu usei a notação poder Fortran para enfatizar quantos anos este material é: )).
Eu corri para este problema com alguns Space Shuttle bit de dados downlink de série mais de 20 anos atrás, quando nós substituímos um hardware interface de $ 10K com um computador Mac. Há uma breve NASA Tecnologia publicado sobre isso há muito tempo. I simplesmente utilizado um elemento 256 tabela de consulta com os bits invertidos (tabela [0x01] = 0x80 etc) após cada byte foi deslocado a partir do fluxo de bits.
Não há inteiros sem sinal em Java. Todos os números inteiros são assinados e em big endian.
No lado do C a cada byte tem tne LSB no início está à esquerda e o MSB no final.
Parece que você está usando LSB como bit menos significativo, não é? LSB geralmente significa byte menos significativo. Endianness não é pouco baseada mas byte base.
Para converter de byte não assinado para um inteiro Java:
int i = (int) b & 0xFF;
Para converter de 32 bits sem sinal little-endian em byte [] para Java longa (a partir do topo da minha cabeça, não testada):
long l = (long)b[0] & 0xFF;
l += ((long)b[1] & 0xFF) << 8;
l += ((long)b[2] & 0xFF) << 16;
l += ((long)b[3] & 0xFF) << 24;
Não há nenhuma maneira isso poderia influenciar qualquer coisa em Java, uma vez que não há nenhuma maneira (não-API direta) para mapear alguns bytes diretamente em um int em Java.
Cada API que faz isso ou algo define semelhantes o comportamento muito precisamente, então você deve olhar a documentação de que API.
Eu lia os bytes, um a um, e combiná-los em um longo valor. Dessa forma, você controlar a ordenação, e o processo de comunicação é transparente.
Se ele se encaixa o protocolo que você usa, considere usar um DataInputStream, onde o comportamento é muito bem definida .
Java é 'Big-endian' como mencionado acima. Isso significa que o MSB de um int é do lado esquerdo se você examinar a memória (em um Intel CPU, pelo menos). O bit de sinal também está no MSB para todos os tipos inteiros Java.
Lendo um inteiro não assinado de 4 bytes de um arquivo binário armazenado por um sistema de 'Little-endian' leva um pouco de adaptação em Java. readInt de DataInputStream () espera formato big-endian.
Aqui está um exemplo que lê um valor não assinado de quatro bytes (como exibido por HexEdit como 01 00 00 00) em um número inteiro com um valor de 1:
// Declare an array of 4 shorts to hold the four unsigned bytes
short[] tempShort = new short[4];
for (int b = 0; b < 4; b++) {
tempShort[b] = (short)dIStream.readUnsignedByte();
}
int curVal = convToInt(tempShort);
// Pass an array of four shorts which convert from LSB first
public int convToInt(short[] sb)
{
int answer = sb[0];
answer += sb[1] << 8;
answer += sb[2] << 16;
answer += sb[3] << 24;
return answer;
}