Java是否在文件I/O中翻转字节顺序



我有简单的C和Java代码,可以从非文本文件中读取整数。当我以十六进制打印结果时,Java代码的字节顺序似乎与C代码不同。示例:

int fd = open("MyFile", O_RDONLY);
int rc = read(fd, &MagicNumber, 4);
printf("MagicNumber is 0x%xn", MagicNumber);

此打印:MagicNumber为0xff017ffe

Java代码是:

FileInputStream fin = new FileInputStream("MyFile");
DataInputStream din = new DataInputStream(fin);
int MagicNumber = din.readInt();
System.out.printf("MagicNumber is 0x%xn", MagicNumber);

它打印:MagicNumber是0xfe7f01ff

输出是相似的,但字节是交换的。我是否错误地执行了文件I/O?我需要做些什么来在C和Java之间一致地读取字节吗?

DataInputStream中的字节顺序是"big-endian"(也称为"网络顺序"(。这几乎被所有二进制网络协议和许多文件格式所使用,尽管小端结构现在占主导地位。

在C代码中,您可以使用ntohl将"网络顺序"转换回"主机顺序",而无需知道主机顺序是小端序还是大端序。

#include <arpa/inet.h>
...
printf("MagicNumber is 0x%xn", ntohl(MagicNumber));

DataInputStream使用big-endian字节顺序读取多字节值,将最高有效字节放在第一位,将最低有效字节放最后。

正如维基百科所说:

大端序是网络协议(IP、TCP、UDP(中的主要顺序。相反,小端序是处理器体系结构(x86、大多数ARM实现、基本RISC-V实现(及其相关内存的主要顺序。文件格式可以使用任意一种排序;有些格式混合使用两者。

由于DataInputStream用于数据交换,因此它使用"网络顺序",也就是big-endian。

要控制字节顺序,应该使用ByteBuffer。这里有一个简单的例子。

FileInputStream fin = new FileInputStream("MyFile");
byte[] buffer = fin.readNBytes(Integer.BYTES);
int magicNumber = ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN).getInt();

最新更新