C 中的 fwrite() 和 Java 中的 readInt() 在 endianess 上有所不同



本机代码:

使用fwrite()。

写编号27
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;
}

使用datainputstream.readint()读取数据(27):

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;
}

o/p

Size : 452984832

好吧,十六进制是 0x1b000000

0x1b27。但是ReadInt()在我的本地编码写作时,将数据读成大元素。。因此,代替0x0000001b,我得到0x1b000000

我的理解正确吗?有人以前遇到过这个问题吗?

来自javadoc的readInt()

此方法适用于读取字节writeInt接口DataOutput

编写的字节

如果您想阅读C程序写的内容,则必须使用java.nio中的设施来进行字节交换。我从来没有这样做,但是我相信您会将数据读为ByteBuffer,将缓冲区的订单设置为ByteOrder.LITTLE_ENDIAN,然后在ByteBuffer上创建IntBuffer视图,如果您有一个值数组,或者仅将ByteBuffer#getInt()用于单个值。

除此之外,我同意@EJP的观点,即数据的外部格式应该是最大兼容性的大范围。

您的代码中有多个问题:

  • 您假设int的大小为4,不一定是正确的,并且由于您想处理32位INT,因此应使用int32_tuint32_t

  • 您必须在二进制中打开文件,以可靠地编写二进制数据。上面的代码将在Windows上失败,以减少琐碎的输出。使用fopen("/data/tmp.log", "wb")

  • 您必须处理endianness。您正在使用该文件在不同的平台之间交换数据,这些平台可能具有不同的本地endianness和/或Endian特定的API。Java似乎使用Big-Endian,又名网络字节顺序,因此您应该使用hton32()实用程序函数转换C平台上的值。这不太可能对PC端的性能产生重大影响,因为此功能通常是内联扩展的,可能是单个指令,并且大部分时间都会花在等待I/O。

这是代码的修改版本:

#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;
}

相关内容

  • 没有找到相关文章

最新更新