Java читает целые числа с прямым или прямым порядком байтов?

Я спрашиваю, потому что я посылаю поток байтов из процесса C в Java. На стороне C 32-разрядное целое число имеет младший байт, первый байт, а старший байт 4-й байт.

Итак, мой вопрос: на стороне Java, когда мы читаем байт, как он был отправлен из процесса C, что является порядком байтов на стороне Java?

Дополнительный вопрос: если порядковый номер на стороне Java не совпадает с отправленным, как я могу конвертировать между ними?

12.12.2008 10:21:17
8 ОТВЕТОВ
РЕШЕНИЕ

Используйте сетевой порядок байтов (big endian), который в любом случае используется Java. Смотрите man htons для разных переводчиков в C.

63
12.12.2008 10:36:30
Я сейчас не на своей Linux-машине, но является ли htons одной из стандартных библиотек?
hhafez 12.12.2008 10:46:21
Согласно h30097.www3.hp.com/docs//base_doc/DOCUMENTATION/V51_HTML/MAN/… это часть стандартной библиотеки c, да
Egil 12.12.2008 10:49:44
htons доступен почти везде, но его нет в ISO C.
MSalters 12.12.2008 11:01:54
Если вам нужно использовать что-то отличное от сетевого порядка байтов, то вы должны либо свернуть свои собственные с помощью побитовых операторов, либо использовать различные версии java.nio.Buffer
Darron 12.12.2008 22:04:13
Согласно его man-странице, она определена в POSIX.1, поэтому она должна быть доступна почти везде. И я помню, как использовал его в Win32, так что это не только в системах POSIX.
Joachim Sauer 12.12.2008 22:04:35

В Java нет целых чисел без знака. Все целые числа подписаны и имеют порядковый номер.

На стороне C каждый байт имеет LSB в начале слева и MSB в конце.

Похоже, вы используете LSB как наименьшее значение, не так ли? LSB обычно обозначает младший байт. Порядковый номер основан не на битах, а на байтах.

Чтобы преобразовать байт без знака в целое число Java:

int i = (int) b & 0xFF;

Чтобы преобразовать из беззнакового 32-разрядного байта с прямым порядком байтов в byte [] в Java long (из головы не проверено):

long l = (long)b[0] & 0xFF;
l += ((long)b[1] & 0xFF) << 8;
l += ((long)b[2] & 0xFF) << 16;
l += ((long)b[3] & 0xFF) << 24;
18
11.02.2018 01:48:26
только что понял: $ так как я должен отправить этот беззнаковый байтовый порядковый номер в мой процесс Java, чтобы прочитать его правильно?
hhafez 12.12.2008 10:28:44
то, что я имею в виду в начале, это то, что lsb находится в начале 4 байтов (это 32-разрядное
hhafez 12.12.2008 10:40:15
Также я конвертирую из C -> Java, а не из Java -> C :)
hhafez 12.12.2008 10:57:23
Ваш код работает нормально, если вы удалите точку с запятой после 0xFF в последних трех строках. Я бы отредактировал его сам, но это изменение не более 6 символов.
Moose Morals 3.03.2016 21:57:55
Прошло почти 8 лет, но наконец кто-то заметил синтаксическую ошибку. Спасибо @MooseMorals :)
Jonas Elfström 4.03.2016 10:04:53

Я читал байты один за другим и объединял их в длинное значение. Таким образом, вы управляете порядком байтов, и процесс коммуникации прозрачен.

3
12.12.2008 10:27:07
Не могли бы вы прокомментировать, почему вы голосуете за меня?
Wouter Lievens 12.12.2008 11:09:10
потому что даже если бы я должен был прочитать каждый байт индивидуально, порядковый номер отправляемого байта был бы неправильным, поэтому мне нужно было бы преобразовать его
hhafez 12.12.2008 21:48:38
Порядковый номер байта? Что это за фигня? Слова имеют чувствительность к порядку байтов, отдельные байты - нет.
Wouter Lievens 19.02.2009 10:13:12
@hhafez Это неправда, байты не имеют порядка байтов, поскольку мы должны понимать, что если вы читаете побайтно, вы, программист, несете ответственность за назначение байтов в правильном месте. Это именно то, что делает DataInputStream, он просто собирает байты вместе с прямым порядком байтов.
nos 20.08.2010 17:15:06
@WouterLievens: я столкнулся с некоторыми устройствами ввода / вывода (например, микросхемой часов реального времени), которые по какой-либо причине отправляют данные в обращенном к битам формате; после получения от них данных необходимо инвертировать биты в каждом байте. Тем не менее, я согласен с вами, что порядковый номер байтов обычно не является проблемой, если только не приходится иметь дело с конкретными, странно спроектированными частями оборудования.
supercat 17.12.2013 17:47:53

Если он соответствует протоколу, который вы используете, рассмотрите возможность использования DataInputStream, где поведение очень хорошо определено .

3
12.11.2017 22:36:16
Он может сделать это, только если его протокол использует ту же последовательность.
Wouter Lievens 12.12.2008 13:09:11
Я исправил ссылку и изменил ее на Java 9, текущую версию. Однако рассматриваемый API был представлен в Java 1.0.
Jens Bannmann 15.11.2017 11:00:33

Нет никакого способа, которым это могло бы повлиять на что-либо в Java, так как не существует (прямого не-API) способа отобразить некоторые байты непосредственно в int в Java.

Каждый API, который делает это или что-то подобное, довольно точно определяет поведение, поэтому вам следует поискать документацию по этому API.

12
12.12.2008 21:37:19
О, конечно, есть. Двоичная математика (&, |, << и т. Д.) Прекрасно работает с байтами и целыми числами. Довольно просто взять произвольные байты и вставить их в целое число.
Herms 12.12.2008 21:57:16
Но если вы сделаете это, вы все равно не сможете определить, какой порядок действий использует ваша JVM для внутреннего использования.
Darron 12.12.2008 22:02:15
Да, но даже там вы напрямую не отображаете. Вы используете арифметику, которая делает именно то, что вы говорите, нет никакой двусмысленности. В C вы всегда можете привести «byte *» к «long *» и отменить ссылку на него. Тогда вам придется заботиться о порядке байтов. В Java нет прямого, неоднозначного способа сделать это.
Joachim Sauer 12.12.2008 22:02:48
Ах я вижу. Вы говорили о броске, а не о двоичной математике. Да, в этом случае ты прав.
Herms 15.12.2008 14:57:04
+1 для «поиска документации», но ПРИМЕЧАНИЕ: 1-е предложение больше не является корректным, поскольку в настоящее время пакет NIO предлагает ByteBuffer, который может отображать байты в примитивы и где вы можете изменить порядок байтов. См. ByteBuffer и ByteOrder
user85421-Banned 12.04.2011 11:13:22

Я наткнулся здесь через Google и получил свой ответ, что Java имеет большой порядок байтов.

Читая ответы, я хотел бы отметить, что байты действительно имеют порядок байтов, хотя, к счастью, если вы имели дело только с «основными» микропроцессорами, вы вряд ли когда-либо сталкивались с такими процессорами, как Intel, Motorola и Zilog. договорились о направлении сдвига их чипов UART и о том, что MSB байта будет 2 ** 7, а LSB будет 2 ** 0 в их ЦП (я использовал обозначение мощности FORTRAN, чтобы подчеркнуть, сколько лет этому материалу :)).

Я столкнулся с этой проблемой с некоторыми последовательными данными нисходящего канала Space Shuttle 20+ лет назад, когда мы заменили аппаратное обеспечение с интерфейсом за 10 000 долларов США на компьютер Mac. Об этом давно опубликовано краткое изложение НАСА. Я просто использовал таблицу поиска из 256 элементов с инвертированными битами (таблица [0x01] = 0x80 и т. Д.) После смещения каждого байта из потока битов.

46
7.09.2016 00:39:59
Отличное понимание! У меня есть этот вопрос и нет ответов в Интернете.
Xolve 28.08.2013 13:46:08
Если кто-то из них публичный, не могли бы вы связать техническую сводку НАСА (и данные последовательного нисходящего потока битов космического челнока pethaps), о которой вы говорите? было бы интересно, я никогда не видел ничего подобного.
n611x007 8.11.2013 16:43:16
Побитовая байтовость также вступает в игру с форматами сжатия, которые используют некоторую форму кодирования Хаффмана (т.е. все они). Для дополнительного удовольствия, JPEG является «побитовым байтом с прямым порядком байтов» (т. Е. Наиболее значимым битом является «первый» бит), а LZ - «битовым байтом с прямым порядком байтов». Однажды я работал над собственным форматом сжатия, который использовал оба формата под капотом. О, это было весело ...
user435779 5.08.2014 14:31:29
Начав в битах, я подумал, что это было бесконечно долго.
Roy Falk 30.03.2016 07:24:23

Java - это «Big-endian», как отмечено выше. Это означает, что MSB int находится слева, если вы исследуете память (по крайней мере, на процессоре Intel). Знаковый бит также находится в MSB для всех целочисленных типов Java.
Чтение 4-байтового целого числа без знака из двоичного файла, хранящегося в системе «Little-endian», требует некоторой адаптации в Java. Функция readInt () объекта DataInputStream ожидает формат с прямым порядком байтов.
Вот пример, который считывает четырехбайтовое значение без знака (как показано 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;        
 }
1
18.02.2019 07:36:33

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

0
4.12.2019 22:16:25
Речь идет о порядке следования инструкций байт-кода, а не о порядке следования данных во время выполнения.
kaya3 4.12.2019 22:23:56