【问题标题】:Reading floats in C++ equivalent in Java在 Java 中读取等效于 C++ 的浮点数
【发布时间】:2018-03-27 18:16:54
【问题描述】:

我有一个二进制文件,它应该包含 32 位浮点数。 这个文件是从 Objective-C 代码中写出来的。 我的任务是用 Java 读取这个文件。

我想我设法用 C++ 做到了:

#include <fstream>
#include <iostream>

int main() {
    float f;
    std::ifstream fin("effect_0.cube", std::ios::binary);
    while (fin.read(reinterpret_cast<char*>(&f), sizeof(float))) {
      std::cout << f << "\n";
    }

    return 0;
}

这就是我在 Java 中解释浮点数的方式

InputStream is = new FileInputStream("effect_0.cube");
DataInputStream dataInputStream = new DataInputStream(is);
float f = dataInputStream.readFloat();

但这会返回完全错误的值。

我在 OSX 上运行所有这些。

文件是here。它非常小。 C++ 的值似乎是正确的,因为它们在正确的范围内,但我在 Java 中得到了完全不同的值。我也提供hexdump -n 16 -s 256:

0000100 00 00 00 00 91 90 90 3e 00 00 00 00 00 00 80 3f
0000110

【问题讨论】:

  • 你能从文件中添加一些你的浮点数的十六进制转储吗?最好是您知道其价值的人。
  • 我上传了文件,有几千字节。
  • 我不关注 StackOverflow 问题的链接。我同意字节顺序的建议。
  • 我添加了 hexdump,所以现在问题更加完整,以供将来参考。
  • 0x3f800000 在 32 位浮点数中是 1.0,所以它绝对是一个 little-endian 文件。

标签: java floating-point binary


【解决方案1】:

C 代码是在 CPU endian order 中编写的,对于 Intel 处理器是 little-endian

DataInputStream 正在按网络字节顺序读取,即big-endian

在 Java 中读取 float 值的最佳方法是使用 ByteBuffer,您可以在其中控制字节序。

示例代码:

try (InputStream is = new FileInputStream("effect_0.cube")) {
    ByteBuffer buf = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN);
    for (int len; (len = is.read(buf.array())) == 4; ) {
        buf.rewind();
        float f = buf.getFloat();
        System.out.println(f);
    }
}

【讨论】:

  • 文件中没有换行符,所以是4字节的块。
  • @RalfKleberhoff 抱歉,我将有问题的代码读取为 C 代码写入 将数据写入文件。
  • 不幸的是,我没有编写该文件的代码。问题中的 C++ 代码正确读取它(我认为)。但我希望你的回答能指出问题(字节序)。我明天试试,然后报告。谢谢!
猜你喜欢
  • 1970-01-01
  • 2013-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多