在Java中读取C++二进制文件

4
我有一个大小为500MB的二进制文件,里面包含许多浮点数数据。这个文件是由一个C++程序编写而来的。在C++中,我可以通过以下方式载入它:
void load(char f_name[], int size, float data[])
{
    std::fstream f_bin(f_name, std::ios::in|std::ios::binary);

    f_bin.seekg(std::ios::beg);
    f_bin.read((char*)data, size*sizeof(float));
    f_bin.close();
}

float *data;
int size = 123456789;
data = new float[size];
load("myFile.bin", size, data);

我可以访问浮点值:data[x];在C++中它工作得相当快。Java中是否有类似的东西?

编辑 阅读了一些资料之后,我目前有以下进展:

        RandomAccessFile f = new RandomAccessFile("C://path//myFile.bin", "r");
        byte[] bytes = new byte[(int)f.length()];
        f.read(bytes);

        float fl = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getFloat();     


        System.out.println(fl);

这段代码输出了第一个浮点数。现在我需要逐个遍历浮点数,并将其放入像float[] data这样的数组中。


1
你可能想要看一下:RandomAccessFile 用于读写字节。 - Matias Cicero
1
我认为这不是“在Java中将文件转换为byte[]”问题的重复:这个问题是关于在Java程序中读取C++生成的数据,特别是浮点数,而另一个问题仅涉及将文件作为字节数组读取。 - Christophe
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - πάντα ῥεῖ
2个回答

3

您可以在Java中实现此操作。

try(FileChannel fc = new RandomAccessFile("myFile.bin", "rw").getChannel()) {
    FloatBuffer fb = fc.map(MapMode.READ_WRITE, 0, fc.size())
                       .order(ByteOrder.nativeOrder()).asFloatBuffer();
    // use fb 
}

这种方法比较快,因为它使用内存映射文件,避免了内存拷贝(在C++中也可以实现同样的效果)。


如果您使用内存映射文件,C语言也非常快速。 - Peter Lawrey
@PeterLawrey,我有一个类似的情况,我已经使用C++以二进制模式将用户定义类的对象写入文件中,并希望从Java中读取。我应该如何修改上面的代码才能实现这一点?您是否可以在您的回答中包含答案? - Chief A
@ChiefA 我已经不熟悉C++了。 - Peter Lawrey

1
Java标准非常精确地规定了浮点数的表示方式:
引用: Java虚拟机规范2.3.2: 浮点类型是float和double,它们概念上与32位单精度和64位双精度格式IEEE 754值和操作相关联,如IEEE二进制浮点算术标准(ANSI / IEEE Std. 754-1985,纽约)中所指定的。
但C++标准并没有给出太多关于此的保证:
引用: C++11标准3.9.1/8:有三种浮点类型:float、double和long double。类型double提供的精度至少与float一样,类型long double提供的精度至少与double一样。(...)浮点类型的值表示是实现定义的。
使用<limits>,您可以以便携的方式了解更多有关浮点数的信息:std::numeric_limits<float>::is_iec559例如,将告诉您是否使用IEC-559 / IEEE-754标准(也称为Java相同)。
  • 如果是,则可以直接使用二进制数据读取浮点数。(根据PoweredByRice的评论进行编辑;实际上,您仍然必须解决潜在的字节序问题,因为IEEE-754没有明确规定。有关如何在C ++端强制指定排序的更多信息,请查看此处。在Java端,您可以强制使用字节顺序或使用默认顺序。)
  • 如果不是,则必须读取字节并编写浮点格式转换程序,这通常很具有挑战性。

这个答案虽然正确地提到了大小的重要性,但没有提到另一半图片即字节序。 - PoweredByRice
@PoweredByRice 实际上,IEEE 754 并没有指定字节序,因此不同的架构之间存在不兼容的风险。 - Christophe
@PoweredByRice 的帖子已经相应地被编辑了。谢谢提示! - Christophe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接