fwrite() в C & readInt() в Java отличаются порядком байтов
Родной код:
написание номера 27 с использованием fwrite().
int main()
{
int a = 27;
FILE *fp;
fp = fopen("/data/tmp.log", "w");
if (!fp)
return -errno;
fwrite(&a, 4, 1, fp);
fclose();
return 0;
}
Считывание данных (27) с использованием DataInputStream.readInt():
public int readIntDataInputStream(void)
{
String filePath = "/data/tmp.log";
InputStream is = null;
DataInputStream dis = null;
int k;
is = new FileInputStream(filePath);
dis = new DataInputStream(is);
k = dis.readInt();
Log.i(TAG, "Size : " + k);
return 0;
}
О / р
Size : 452984832
Хорошо что в гексе есть 0x1b000000
0x1b
является 27
, Но readInt () читает данные с прямым порядком байтов, в то время как моя нативная кодировка записывает с прямым порядком байтов., Итак, вместо 0x0000001b
я получил 0x1b000000
,
Правильно ли мое понимание? Кто-нибудь сталкивался с этой проблемой раньше?
2 ответа
От Javadoc для readInt()
:
Этот метод подходит для чтения байтов, написанных
writeInt
метод интерфейсаDataOutput
Если вы хотите прочитать что-то, написанное программой на C, вам придется самостоятельно поменять байт, используя средства java.nio
, Я никогда не делал этого, но я верю, что вы прочитаете данные в ByteBuffer
установите порядок буфера в ByteOrder.LITTLE_ENDIAN
а затем создать IntBuffer
вид на ByteBuffer
если у вас есть массив значений, или просто использовать ByteBuffer#getInt()
для одного значения.
Помимо всего этого, я согласен с @EJP, что внешний формат данных должен иметь порядок байтов для лучшей совместимости.
В вашем коде есть несколько проблем:
Вы предполагаете, что размер
int
является4
, это не обязательно верно, и, так как вы хотите иметь дело с 32-битными целыми числами, вы должны использоватьint32_t
или жеuint32_t
,Вы должны открыть файл в двоичном формате больше, чтобы надежно записать двоичные данные. Приведенный выше код не будет работать в Windows для менее тривиального вывода. использование
fopen("/data/tmp.log", "wb")
,Вы должны иметь дело с порядком байтов. Вы используете этот файл для обмена данными между различными платформами, которые могут иметь различные собственные API-интерфейсы с прямым порядком байтов и / или. Похоже, что в Java используется порядок байтов с прямым порядком байтов, иначе говоря, вы должны преобразовать значения на платформе C с помощью
hton32()
вспомогательная функция. Маловероятно, что это окажет значительное влияние на производительность на стороне ПК, так как эта функция обычно расширяется, возможно, в виде одной инструкции, и большую часть времени будет уделено ожиданию ввода-вывода в любом случае.
Вот модифицированная версия кода:
#include <endian.h>
#include <stdint.h>
#include <stdio.h>
int main(void) {
uint32_t a = hton32(27);
FILE *fp = fopen("/data/tmp.log", "wb");
if (!fp) {
return errno;
}
fwrite(&a, sizeof a, 1, fp);
fclose();
return 0;
}