Pytam, ponieważ wysyłam strumień bajtów z procesu C do Javy. Po stronie C 32-bitowa liczba całkowita ma LSB to pierwszy bajt, a MSB to czwarty bajt.
Moje pytanie brzmi: po stronie Javy, kiedy odczytujemy bajt wysłany z procesu C, czym jest endian po stronie Javy?
Pytanie uzupełniające: Jeśli endian po stronie Java nie jest tym samym, co wysłany, jak mogę dokonać konwersji między nimi?
java
endianness
hhafez
źródło
źródło
Odpowiedzi:
Użyj sieciowej kolejności bajtów (big endian), która i tak jest taka sama, jakiej używa Java. Zobacz man htons dla różnych tłumaczy w C.
źródło
Natknąłem się tutaj przez Google i otrzymałem odpowiedź, że Java to big endian .
Czytając odpowiedzi, chciałbym zwrócić uwagę, że bajty rzeczywiście mają kolejność endian, chociaż na szczęście, jeśli miałeś do czynienia tylko z mikroprocesorami „głównego nurtu”, prawdopodobnie nie spotkałeś ich nigdy jako Intel, Motorola i Zilog zgodzili się co do kierunku przesunięcia ich układów UART i że MSB bajtu będzie,
2**7
a LSB będzie2**0
w ich procesorach (użyłem notacji mocy FORTRAN, aby podkreślić, ile lat ma ten materiał :)).Napotkałem ten problem z niektórymi szeregowymi danymi łącza w dół Space Shuttle 20+ lat temu, kiedy wymieniliśmy sprzęt interfejsu za 10 000 USD na komputer Mac. Już dawno temu opublikowano krótki opis techniczny NASA. Po prostu użyłem 256-elementowej tabeli wyszukiwania z odwróconymi bitami (
table[0x01]=0x80
itp.) Po przesunięciu każdego bajtu ze strumienia bitów.źródło
W Javie nie ma liczb całkowitych bez znaku. Wszystkie liczby całkowite są podpisane i zapisane w big endian.
Wygląda na to, że używasz LSB jako najmniej znaczącego kawałka, prawda? LSB zwykle oznacza najmniej znaczący bajt. Endianness nie jest oparty na bitach, ale na bajtach.
Aby przekonwertować bajt bez znaku na liczbę całkowitą Java:
int i = (int) b & 0xFF;
Aby przekonwertować z 32-bitowego little-endian bez znaku w bajcie [] do języka Java (od początku mojej głowy, nie testowane):
long l = (long)b[0] & 0xFF; l += ((long)b[1] & 0xFF) << 8; l += ((long)b[2] & 0xFF) << 16; l += ((long)b[3] & 0xFF) << 24;
źródło
Nie ma sposobu, aby mogło to wpłynąć na cokolwiek w Javie, ponieważ nie ma (bezpośredniego, innego niż API) sposobu mapowania niektórych bajtów bezpośrednio na int w Javie.
Każde API, które robi to lub coś podobnego, dość precyzyjnie definiuje zachowanie, więc powinieneś zajrzeć do dokumentacji tego API.
źródło
Czytałem bajty jeden po drugim i łączyłem je w długą wartość. W ten sposób kontrolujesz endianness, a proces komunikacji jest przejrzysty.
źródło
Jeśli pasuje do używanego protokołu, rozważ użycie DataInputStream, gdzie zachowanie jest bardzo dobrze zdefiniowane .
źródło
Jak wspomniano powyżej, Java to „Big-endian”. Oznacza to, że MSB int znajduje się po lewej stronie, jeśli zbadasz pamięć (przynajmniej na procesorze Intela). Bit znaku znajduje się również w MSB dla wszystkich typów całkowitych Java.
Odczyt 4-bajtowej liczby całkowitej bez znaku z pliku binarnego przechowywanego w systemie „Little-endian” wymaga pewnych adaptacji w Javie. Funkcja readInt () DataInputStream oczekuje formatu Big-endian.
Oto przykład, który odczytuje czterobajtową wartość bez znaku (wyświetlaną przez HexEdit jako 01 00 00 00) na liczbę całkowitą o wartości 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; }
źródło
java force w istocie big endian: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.11
źródło
byte[] bbb = ByteBuffer.allocate(4).putFloat(0.42f).array();
produkowanebyte
tablicę, która jest odwrotnością tego, co mójC/C++
produkowane. W związku z tym duże możliwości języka Java mają wpływ nawet na dane w czasie wykonywania.