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

时间:2015-04-30 10:46:14

标签: c++ serialization binaryfiles platform-independent

我有一个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位字长,小字节序或大端字节顺序。

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

3 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:2)

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

以下是代码现在的样子:

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];
        }
    }
}

答案 2 :(得分:1)

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

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