Чи читає Java цілі числа в маленькому ендіані чи великому ендіані?


94

Я запитую, тому що я надсилаю потік байтів із процесу C на Java. З боку С 32-бітове ціле число має LSB - перший байт, а MSB - 4-й байт.

Отже, моє запитання: На стороні Java, коли ми читаємо байт так, як він був надісланий із процесу C, що з боку Java є ендіаном ?

Наступне запитання: Якщо ендіан на стороні Java не такий, як надісланий, то як я можу конвертувати між ними?


1
Ось моя мнемоніка для цього, тому я не забуду: мова є не апаратним, а віртуальним, мовою Інтернету. Порядок мережевих байтів є великим ендіаном . Тому Java є великим ендіаном .
truthadjustr

Відповіді:


66

Використовуйте порядок мережевих байтів (великий ендіан), який такий же, як використовує Java. Див. Людині htons для різних перекладачів у C.


Я зараз не в моєму linux box, але хітон є однією зі стандартних ліб?
hhafez

Відповідно до h30097.www3.hp.com/docs//base_doc/DOCUMENTATION/V51_HTML/MAN/… її частина стандартної бібліотеки c, так
Egil

1
htons доступний майже скрізь, але це не в ISO C.
MSalters

1
Якщо вам потрібно скористатися чимось, окрім порядку мережевих байтів, тоді ви або згорнете свій власний оператор з побітними операторами, або використовуйте різні версії java.nio.Buffer
Darron

1
Відповідно до його підручної сторінки, вона визначена в POSIX.1, тому вона має бути доступною майже скрізь. І я, мабуть, пам’ятаю, що використовував його в Win32, тому це стосується не лише систем POSIX.
Йоахім Зауер

47

Я натрапив сюди через Google і отримав свою відповідь, що Java - великий ендіанець .

Читаючи відповіді, я хотів би зазначити, що байти дійсно мають порядок ендіан, хоча милосердно, якщо ви мали справу лише з "основними" мікропроцесорами, ви навряд чи коли-небудь стикалися з ним як Intel, Motorola та Zilog all домовились про напрямок зсуву своїх мікросхем UART і про те, що MSB байта буде, 2**7а LSB буде 2**0в їх процесорах (я використовував нотацію потужності FORTRAN, щоб підкреслити, скільки років цей матеріал :)).

Я зіткнувся з цією проблемою з деякими серійними даними про передачу низхідної лінії Space Shuttle 20 років тому, коли ми замінили апаратне забезпечення інтерфейсу в 10 000 доларів на комп'ютер Mac. Про це давно опубліковано короткий текст NASA Tech. Я просто використав таблицю пошуку 256 елементів з бітами, поверненими ( table[0x01]=0x80і т.д.) після зміщення кожного байта з потоку бітів.


Прекрасне розуміння! У мене це запитання і відповіді в Інтернеті немає.
Xolve

якщо хтось із них загальнодоступний, чи можете ви зв’язати технічний короткий опис NASA (і, можливо, серійні дані про космічний човник), про який ви говорите? було б захоплююче, я ніколи такого не бачив.
n611x007

3
Побітова ендіантність також грає з форматами стиснення, які використовують певну форму кодування Хаффмана (тобто всі вони). Для додаткової забави JPEG - "побітовий біт-ендіан" (тобто, найзначніший біт - "перший" біт), а LZ - "побітовий мало-ендіанський". Я колись працював над фірмовим форматом стиснення, який використовував обидва формати під кришкою. О, це було весело ...
user435779

Почавши в шматочках, я подумав, ЩО це є довгомірністю.
Рой Фолк

20

У Java немає непідписаних цілих чисел. Всі цілі числа підписані та великими ендіанами.

З боку С кожен байт має TSB на початку, зліва, а MSB в кінці.

Здається, ви використовуєте LSB як найменший істотний біт, чи не так? LSB зазвичай означає найменш значущий байт. Ендіанс заснований не на бітах, а на байтах.

Для перетворення з непідписаного байта в ціле число Java:

int i = (int) b & 0xFF;

Щоб конвертувати з непідписаного 32-бітового маленького ендіана в байті [] до Java довго (зверху голови, не перевірено):

long l = (long)b[0] & 0xFF;
l += ((long)b[1] & 0xFF) << 8;
l += ((long)b[2] & 0xFF) << 16;
l += ((long)b[3] & 0xFF) << 24;

щойно зрозумів, що: $ так, як я повинен надіслати цей маленький ендіаніст моєму Java-процесу, щоб правильно його прочитати?
hhafez

Що я маю на увазі під початком, це те, що lsb знаходиться на початку 4-х байтів (це 32-бітний
підпис

Також я конвертую з C -> Java не з Java -> C :)
hhafez

Ваш код працює нормально, доки ви видалите напівколонку після 0xFF в останніх трьох рядках. Я б сам це відредагував, але це зміна менше 6 символів.
Moose Morals

1
Минуло майже 8 років, але нарешті хтось помітив помилку синтаксису. Дякую @MooseMorals :)
Jonas Elfström

12

Це не може вплинути на що-небудь в Java, оскільки немає (прямого не-API) способу відображення деяких байтів безпосередньо в інту в Java.

Кожен API, який робить це чи щось подібне, визначає поведінку досить точно, тому слід переглянути документацію цього API.


3
О, звичайно, є. Двійкова математика (&, |, << тощо) працює чудово на байтах та ints. Досить просто взяти довільні байти і вставити їх у ціле число.
Гермс

8
Але якщо ви це зробите, ви все одно не можете сказати, яку виправданість використовує ваш JVM всередині.
Даррон

4
Так, але навіть там ви безпосередньо не відображаєте. Ви використовуєте арифметику, яка робить саме те, що вам сказали, двозначності немає. У C ви завжди можете кинути "байт *" на "довгий *" і знеструмити його. Тоді вам доведеться дбати про ендіатизм. У Java немає прямого, неоднозначного способу зробити це.
Йоахім Зауер

А, бачу. Ви говорили про акторський склад, а не про двійкову математику. Так, у цьому випадку ти маєш рацію.
Гермс

10
+1 для "пошуку документації", але ПРИМІТКА: 1-е речення більше не є правильним, оскільки нині пакет NIO пропонує ByteBuffer, який може відображати байти до примітивів і де ви можете змінити порядок байт. Дивіться: ByteBuffer та ByteOrder
користувач85421,

3

Я читав байти один за іншим, і об'єднати їх в довгострокову вартість. Таким чином ви контролюєте цілеспрямованість, а процес спілкування прозорий.


Хочете прокоментувати, чому ви мене голосуєте?
Wouter Lievens

тому що навіть якщо я, де читати кожен байт окремо, витривалість байта, який він надсилає, була б невірною, тому мені потрібно було б його перетворити
hhafez

23
Витривалість байта? Що це, чорт візьми? Слова чутливі до витримки, окремі байти - ні.
Wouter Lievens

3
@hhafez Це неправда, байти не мають випромінювання, наскільки ми повинні бути стурбовані, якщо ви читаєте байт за байтом, ви, програміст, відповідальні за призначення байтів у потрібне місце. Це саме те, що робить DataInputStream, він просто збирає байти разом великим способом під кришками.
нос

2
@WouterLievens: я стикався з деякими пристроями вводу-виводу (наприклад, мікросхемою годинника в режимі реального часу), які з будь-якої причини надсилають дані у бітовому зворотному форматі; одержавши від них дані, потрібно повернути біти в кожному байті. Я погоджуюсь з вами, що нестабільність байтів, як правило, не є проблемою, якщо тільки не доводиться мати справу з певним чином розробленим обладнанням.
supercat

3

Якщо він відповідає протоколу, який ви використовуєте, подумайте про використання DataInputStream, де поведінка дуже чітко визначена .


1
Він може це зробити лише в тому випадку, якщо його протокол використовує ту саму витривалість.
Wouter Lievens

Я виправив посилання та змінив його на вказівку на Java 9, поточну версію. Розглянутий API був представлений в Java 1.0.
Єнс Банманн

2

Java - "Біг-ендіан", як зазначено вище. Це означає, що MSB інта знаходиться зліва, якщо ви вивчаєте пам'ять (принаймні на процесорі Intel). Біт знаків також є в MSB для всіх цілих типів Java.
Читання 4-байтного безпідписаного цілого числа з двійкового файлу, що зберігається системою "Little-endian", потребує певної адаптації в Java. DataIputStream readInt () очікує формат Big-endian.
Ось приклад, який читає чотири байтне безпідписане значення (як відображається HexEdit як 01 00 00 00) у ціле число зі значенням 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;        
 }

На що посилається "зазначене вище"? Порядок відображення відповідей SO може змінюватись.
LarsH

0

java force дійсно великий ендіан: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.11


3
Йдеться про витривалість інструкцій байт-коду, а не про витривалість даних під час виконання.
kaya3

Я голосую. Цей фрагмент byte[] bbb = ByteBuffer.allocate(4).putFloat(0.42f).array();створив byteмасив, який є зворотним до того, що я C/C++створив. Тому велика витривалість Java діє навіть у даних під час виконання.
truthadjustr
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.