fstream产生了非常奇怪的行为

时间:2017-06-19 23:44:39

标签: c++ debugging fstream

当我向文件流写一个double,然后写一个整数时,整数作为额外数字附加到double,我不知道它为什么会发生。有人可以帮我解释一下吗?最小的例子:

#include <iostream>
#include <fstream>

int main()
{
    std::fstream s("test.bin", std::fstream::binary | std::fstream::trunc | std::fstream::in | std::fstream::out);
    s << 3.14;
    int n = 36;
    s << n;
    s.seekp(0);
    double d;
    s >> d;
    printf("%f\n", d);
}

我期待发生的事情:

  • 程序打开一个名为test.bin
  • 的文件
  • 它将值3.14写入文件(8个字节)
  • 它将值36写入文件(4个字节)
  • 它会跳回缓冲区的开头
  • 它读取双类型值(8字节)
  • 打印值(显示3.140000

实际发生的事情: 程序输出3.143600 - 我完全不知道为什么会这样。它没有任何意义。如果我更改初始值,例如从3.14更改为18.3204,则会输出18.320436。发生了什么事?

2 个答案:

答案 0 :(得分:2)

  

它将值3.14写入文件(8字节)
  它将值36写入文件(4个字节)

这不是发生的事情。 >><<和朋友以人类可读的形式阅读和写入值。

s << 3.14;将数字3,句号,数字1和数字4写入文件(4个ASCII字符)。 s << 36;将数字3和数字6写入文件(2个ASCII字符)。

该文件包含6个ASCII字符:a 3,一个句号,一个1,一个4,一个3和一个6.或者正如任何普通人所写的那样:它包含3.1436

s >> d;通过文件中的字符读取一个数字,直到找到一个看起来不像数字的字符,然后将读取的字符转换为数字(就像转换它们一样)如果你输入cin)。它读取3,句号,1,4,3,6,然后产生数字3.1436。

答案 1 :(得分:0)

在对流进行操作时,<<>>执行格式化访问。忽略幕后伏都教,<<写字符串,>>读取字符串。所以

s << 3.14;` 

将3.14转换为字符串并将字符串写入文件。与s << n;相同。

您现在有一个包含字符&#34; 3.1436&#34;的文件。

s >> d;

将文件读取为字符串,以查找分隔空格或任何其他无法转换为double值的字符。由于文件中没有分隔3.14和36,因此3.1436作为单个数字被读回。

您需要做的是使用未经格式化的原始读写:

#include <iostream>
#include <fstream>

int main()
{
    std::fstream s("test.bin",
                   std::fstream::binary | std::fstream::trunc |
                       std::fstream::in | std::fstream::out);
    double d = 3.14;
    int n = 36;
    if (s.write((char*) &d, sizeof(d)) &&
        s.write((char*) &n, sizeof(n)))
    { 
        s.seekp(0);
        if (s.read((char*) &d, sizeof(d)))
        { 
            std::cout << d;
        }
        else 
        { 
             std::cerr << "failed to read\n";
        }
    }
    else
    {
         std::cerr << "failed to write\n";
    }
}

始终测试IO以确保其成功。

还要注意,这不是便携式的。写在一台机器上的文件不保证在另一台机器上可读,而不需要更加小心。 int可能大小不同,请注意我的儿子the endian!字节的顺序......

Documentation on write

Documentation on read