从二进制文件中读写C++双精度浮点数

4
我希望为一个占用过多内存的程序执行磁盘I/O操作。我使用双精度矩阵,并认为将它们作为字节写入磁盘是最快的方式(我需要保留双精度)。如何实现可移植性?我在这里找到了这段代码(这里),但作者说它不具备可移植性...
#include <iostream>
#include <fstream>

int main()
{
    using namespace std;

    ofstream ofs( "atest.txt", ios::binary );

    if ( ofs ) {
        double pi = 3.14;

        ofs.write( reinterpret_cast<char*>( &pi ), sizeof pi );
        // Close the file to unlock it
        ofs.close();

        // Use a new object so we don't have to worry
        // about error states in the old object
        ifstream ifs( "atest.txt", ios::binary );
        double read;

        if ( ifs ) {
            ifs.read( reinterpret_cast<char*>( &read ), sizeof read );
            cout << read << '\n';
        }
    }

    return 0;
}

2
这段代码不具备可移植性,因为sizeof(double)在不同平台上可能会有所不同。你需要检查一下,但除此之外,示例代码是可以的。 - spraff
1
我更担心double的字节顺序,因为这更有可能改变(特别是如果与任何嵌入式硬件交互)。 - Mark B
真实的情况是,尽管用“可能”的术语来谈论和思考是一个坏习惯。如果你真的关心可移植性,那么它就没有程度之分。 - spraff
3个回答

5
如何实现可移植性?
可移植性有不同的定义和级别。如果您只是在一台机器上编写并在同一台机器上阅读这些代码,那么您所关心的唯一可移植性就是这些代码是否被良好定义。(它是的。)
如果您想要跨多个平台编写可移植代码,您需要编写字符串值而不是二进制值。
但请注意,您的代码缺乏适当的错误处理。它没有检查文件是否能够被打开并成功写入。

@Luchian:非常抱歉。:) - sbi
我的“可移植性水平”从个人电脑(在Windows和Linux / Unix上)到集群。我想要写字节,因为我需要最大的速度和最小的大小。 - Andy
@Andy:你误解了。你想在Windows机器上编写这些文件,然后在Unix机器上读取它们吗?还是你想在同一台机器上编写和读取它们(但代码应该在任何机器上都能运行)? - sbi
抱歉 :) 输入/输出将在同一台机器上进行。使用Boost序列化库是否是一个好的选择? - Andy
@Andy:我没有使用过它,但我认为它可以写入/读取字符串化的数据。如果仅在同一台机器上进行操作,那么写入二进制确实会更快。而且它应该可以在任何(一个)平台上运行。 - sbi

2
我认为可移植性问题只会在您在一台不同的机器上写入文件并从中读取时出现。然而,既然您说由于内存限制而想要读/写文件,我只能假设您会一次在一台机器上进行读/写操作。这应该是可行的。

1
他可能是在讲二进制表示法的一般性问题,而不仅仅是 sizeof。 C - 浮点数(floats,doubles)的序列化 规范根本没有指定浮点数的二进制表示法。 大多数编译器遵循 IEEE 标准,因此如果您知道目标平台,进行一些单元测试应该可以确保您想要的行为。

2
但不要忘记,一些机器使用小端IEEE格式,而一些机器使用大端IEEE格式 - 大致上是英特尔和“其他所有人”(PPC,SPARC等)。 - Jonathan Leffler
是的,绝对正确。我认为重点在于您需要编写测试以确保在您希望针对的每个平台上都具有有效性。 - Tom Kerr

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