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

C++ C++;:如何保存与平台无关的二进制文件?,c++,serialization,binaryfiles,platform-independent,C++,Serialization,Binaryfiles,Platform Independent,我有一个3D卷,表示为vector of vector of vector of float,我想保存到一个二进制文件中。(这是从CT扫描仪的X射线图像重建的密度体。) 现在,我可以通过以下方式来实现: //iterate through the volume for (int x = 0; x < _xSize; ++x){ for (int y = 0; y < _ySize; ++y){ f

我有一个3D卷,表示为vector of vector of vector of float,我想保存到一个二进制文件中。(这是从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));
                }
            }
        }
//遍历卷
对于(int x=0;x
这基本上是可行的。然而,我在问自己,这在多大程度上是平台独立的。我想产生一个文件,这是相同的,无论它是在哪个系统上创建的。因此,可能有运行Windows、Linux或Mac的机器,它们可能有32位或64位的字长和小端或大端字节顺序


我想如果我像上面那样做的话,情况就不会是这样了。现在我如何才能做到这一点?我听说过序列化,但我还没有找到一个具体的解决方案。

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


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

谷歌协议缓冲区:免费,编码为二进制,有几种语言,在大多数平台上也能工作。对于您的要求,我会认真考虑GPB。不过要小心,谷歌已经发布了几个版本,它们并不总是向后兼容的,即旧数据不一定能被新版本的GPB代码读取。我觉得它仍在发展中,而且还会发生进一步的变化,如果您的项目也要经过多年的发展,这将是一个麻烦


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

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

下面是代码现在的样子:

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];
        }
    }
}
QDataStream out(&file);
setFloatingPointPrecision(QDataStream::SinglePrecision);
out.setByteOrder(QDataStream::LittleEndian);
对于(int x=0;xout我使用Qt
Datastream
类解决了这个问题。Qt无论如何都是我项目的一部分,因此额外的工作量是最小的。我可以准确地告诉
Datastream
对象我想用单精度(32位)还是双精度(64位)保存我的
浮点值如果我想使用小端字节顺序或大端字节顺序。这完全满足我的需要;我不需要序列化对象。我现在保存的文件在所有平台上都有完全相同的格式(至少应该是这样),这就是我所需要的。这些信息将由第三方应用程序读取(字节顺序,精度)将提供。因此,确切地说,如何保存浮点数并不重要,但我知道如何保存浮点数,并且无论在哪个平台上运行程序,这都是一致的

下面是代码现在的样子:

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];
        }
    }
}
QDataStream out(&file);
setFloatingPointPrecision(QDataStream::SinglePrecision);
out.setByteOrder(QDataStream::LittleEndian);
对于(int x=0;xout我很惊讶没有提到外部数据表示的
标题。我相信它在所有Unix上都有,甚至可以在Windows上工作:


XDR将所有基本数据类型存储在big-endian中,并负责为您进行转换。

我很惊讶没有提到外部数据表示的
头。我相信它在所有Unix上都可以使用,甚至可以在Windows上使用:

XDR以big-endian格式存储所有基本数据类型,并为您处理转换。

不使用二进制格式。有许多不错的文本格式可用,如果没有适合您的格式,您可以很容易地创建自己的专用格式