C++:如何保存与平台无关的二进制文件?

C++: How to save platform independent binary files?

我有一个 3D 体积,表示为浮点向量的向量向量,我想将其保存到二进制文件中。 (这是根据 CT 扫描仪的 X 射线图像重建的密度体积。)

现在,我可以通过以下方式执行此操作:

        //iterate through the volume
        for (int x = 0; x < _xSize; ++x){
            for (int y = 0; y < _ySize; ++y){
                for (int z = 0; z < _zSize; ++z){
                    //save one float of data
                    stream.write((char*)&_volume[x][y][z], sizeof(float));
                }
            }
        }

这基本上行得通。但是,我问自己这在多大程度上独立于平台。我想生成一个相同的文件,无论它是在哪个系统上创建的。所以可能有机器 运行 Windows、Linux 或 Mac,它们可能有 32 位或 64 位字长和小端或大端字节顺序。

我想如果我按照上面的方式这样做,情况就不会是这样了。现在我怎么能做到这一点?我听说过序列化,但我还没有找到针对此实例的具体解决方案。

Google Protocol Buffers:免费,编码为二进制,提供多种语言,也适用于大多数平台。对于您的要求,我会认真考虑 GPB。不过要小心,Google 已经发布了几个版本,它们并不总是向后兼容,即旧数据不一定能被新版本的 GPB 代码读取。我觉得它仍在发展,并且会发生进一步的变化,如果您的项目也将在很多年内发展,这可能会很麻烦。

ASN.1,它们的祖父,非常好的模式语言(可以设置值和大小约束,这是避免缓冲区溢出的好方法,并在自动生成的代码正确的情况下自动验证数据流),一些免费工具,请参阅 this page(虽然大部分都是要花钱的)。 GPB 的模式语言是对 ASN.1 的拙劣模仿。

我使用 Qt Datastream class 解决了这个问题。不管怎样,Qt 是我项目的一部分,所以额外的工作量很小。如果我想使用单精度(32 位)或双精度(64 位)保存我的 floats,以及我想使用小端还是大端字节顺序,我可以准确地告诉 Datastream 对象。这足以满足我的需要;我不需要序列化对象。我现在保存的文件在所有平台上都具有完全相同的格式(至少它们应该如此),这就是我所需要的。之后它们将被提供这些信息(字节顺序、精度)的第 3 方应用程序读取。所以说这并不重要如何我的花车是如何保存的,但我知道它们是如何保存的,而且无论在什么情况下,这都是一致的你是哪个平台运行程序。

下面是代码现在的样子:

QDataStream out(&file);
out.setFloatingPointPrecision(QDataStream::SinglePrecision);
out.setByteOrder(QDataStream::LittleEndian);

for (int x = 0; x < _xSize; ++x){
    for (int y = 0; y < _ySize; ++y){
        for (int z = 0; z < _zSize; ++z){
            //save one float of data
            out<<_volume[x][y][z];
        }
    }
}

我很惊讶没有提到 <rpc/xdr.h> header,用于外部数据表示。我相信它适用于所有 unix,甚至可能适用于 Windows: https://github.com/ralight/oncrpc-windows/blob/master/win32/include/rpc/xdr.h

XDR 以大端存储所有原始数据类型,并为您处理转换。