现在我有一个程序,我必须从二进制文件中读取数字。数字是小端的,我必须转换成 java 代码的大端。我没有得到任何东西。所以任何人都可以发布我该怎么做。求求你了,谢谢你。
5 回答
Read it using nio and a ByteBuffer
on which you'll have done .order(ByteOrder.LITTLE_ENDIAN)
.
Looks like Guava has beta support for it.
Appache commons has a LittleEndianInputStream, since years
到目前为止的答案很好,但我不得不承认,这些天我在 .NET 中花费的时间比在 java 中花费的时间更多。
但是,我确实觉得除了其他人在这里提出的答案之外,实际上可能值得发布一个答案来描述小端和大端之间的区别。
通常,当我看到这样的问题时,人们并没有意识到这实际上是一个非常简单的任务,只需要大约 5 分钟就可以完成。
Endiness 是关于给定数字的字节实际存储在二进制文件中的顺序。
让我们举一个 16 位“短整数”的简单示例(可以受此影响的最小大小)
如果您停止以“字节”的形式考虑这一点,那么您会立即看到 16 位实际上等于 2 个字节。
现在,如果您开始将这些字节分解为最低和最高顺序,您实际上会得到一个低位字节和一个高位字节。
如果我们想象一下,我们有值 511,它由 2 个字节表示
1
和
256
为什么?
数字中的位位置是 2 的幂,如果你从右到左遍历 2 的幂的位,你会得到:
128 64 32 16 8 4 2 1
如果将所有这些列加在一起,您会看到可以得到的最大值是 255
当所有位都已满时,您必须进入下一位,因此为了获得 511 我们必须拥有
256 128 64 32 16 8 4 2 1
通过拆分成字节的扩展,它真的变成了
1 | 128 64 32 16 8 4 2 1
与 | 表示两个 8 位字节之间分割的字符。
或以图形形式
-------------
| 1 | 255 |
-------------
我不会深入研究二进制,否则我最终会偏离主题,但是那里有很多不错的参考资料,例如 Wikipedia 上的这个:
http://en.wikipedia.org/wiki/Binary_number
回到我们的字节......
当您将这些字节写入文件时,您可以先写入 1,然后再写入 255,也可以先写入 255,然后再写入 1
如果你先写 1,那么这就是所谓的“Big Endian”,因为你先写两个字节的最大(最高)值。
如果你先写 255,那么你先写两个值中最小的(较低的),因此命名为“Little Endian”
你如何从一种转换到另一种?
这真的很容易,如果这些值作为“Little Endian”值存储在文件中,那么您基本上需要执行以下操作:
Read One Byte into A
Read One Byte into B
Make 16 bit Result = (B << 8) + A
如果它作为“Big Endian”值存储在文件中
Read One Byte into A
Read One Byte into B
Make 16 bit Result = (A << 8) + B
其他数字类型也很简单,取一个普通的 32 位整数......
分解它等于 4 , 8 位字节
-----------------
| 4 | 3 | 2 | 1 |
-----------------
其中 1 为最低,4 为最高。
在“Little Endian”中,字节将按如下方式存储在文件中:
-----------------
| 1 | 2 | 3 | 4 |
-----------------
将其读回:
Read One Byte into A
Read One Byte into B
Read One Byte into C
Read One Byte into D
Make 32 bit Result = (D << 24) + (C << 16) + (B << 8) + A
在“大端”中:
-----------------
| 4 | 3 | 2 | 1 |
-----------------
将其读回:
Read One Byte into A
Read One Byte into B
Read One Byte into C
Read One Byte into D
Make 32 bit Result = (A << 24) + (B << 16) + (C << 8) + D
所以你看,只要你知道如何读取单个字节(在任何语言中)你真的不需要任何额外的例程或库调用,你只需要一点左移......
对于那些好奇的人:
写一个 32 位整数为
“小端”:
Make R = 32 bit integer to store
Make 8 bit Value A = R AND 255
Make 8 bit Value B = (R >> 8) AND 255
Make 8 bit Value C = (R >> 16) AND 255
Make 8 bit Value D = (R >> 24) AND 255
Write A as byte to file
Write B as byte to file
Write C as byte to file
Write D as byte to file
“大端”:
Make R = 32 bit integer to store
Make 8 bit Value A = R AND 255
Make 8 bit Value B = (R >> 8) AND 255
Make 8 bit Value C = (R >> 16) AND 255
Make 8 bit Value D = (R >> 24) AND 255
Write D as byte to file
Write C as byte to file
Write B as byte to file
Write A as byte to file
您可能在代码中做错了什么。我最近写了一篇关于如何读写二进制文件以及如何转换字节序的博客文章。将数据读入字节后,您需要调用 flip()
FileChannel fc = (FileChannel) Files.newByteChannel(Paths.get(filename), StandardOpenOption.READ);
ByteBuffer byteBuffer = ByteBuffer.allocate((int)fc.size());
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
fc.read(byteBuffer);
byteBuffer.flip();
http://pulasthisupun.blogspot.com/2016/06/reading-and-writing-binary-files-in.html