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;
}
Другие вопросы по тегам