【问题标题】:Neither fwrite nor write work in my C++ program在我的 C++ 程序中既不写也不写工作
【发布时间】:2013-01-05 19:10:10
【问题描述】:

我正在为我的学校项目编写一个涉及大量二进制文件的 c++ 程序。我的问题是,每当编译器遇到写入语句(我的意思是使用 fstream::write 将数据从类的对象写入二进制文件)时,执行就会停止并且我会收到异常终止消息。我确定“写”语句是问题所在,因为在它执行之前的每个语句,而下一个语句没有。当我改用 fwrite 时,问题似乎已经解决,但后来我发现数据实际上并没有写入文件。我尝试在另一个函数或使用“this”指针的方法中将对象写入文件,但计算机似乎不接受其中任何一个。

该程序在几天前之前运行良好,但似乎突然停止运行。我无法附上源代码,因为问题遍布整个程序,有 5000 多行。但是,以下是导致问题的示例:

bottle b; //bottle is a class
fstream file ("Bottle.dat",ios::out|ios::binary);
file.write ((char*)&b,sizeof(b));

作为替代,我也尝试过

FILE*fptr=fopen ("Bottle.dat","w");
fwrite (&b, sizeof(b), 1, fptr);

前者导致异常终止,后者不起作用。编译期间没有错误消息。有谁能够帮助我?不过,我是编程的新手(还在上高中),所以请尽量保持简单。谢谢!

编辑:也许这会是更好的例子。

class irrigation
{   int n,i,itime[20],t[20];
    float amt[20],water[20];
protected:
    float irr;
public:
    float getirr()
    {   return irr;
    }
    void irrigate();
};

void irrigate_calc()
{   fstream file ("Irrigate.dat",ios::in|ios::binary);
    irrigation i;
    file.read ((char*)&i,sizeof(i));
    file.close();
    i.irrigate();
    fstream file1 ("Irrigate.dat",ios::out|ios::binary);
    file1.write ((char*)&i,sizeof(i));
    file1.close();
}

据我所知,当我打开一个文件进行读取,再次关闭它然后打开它进行写入时,就会出现问题。当然,我确实尝试过直接在 ios::in、ios::out 和 ios::ate 模式下一起打开文件,但这搞砸了,大时间。

编辑 2:同一个程序面临的另一个问题是,一些正常的 cout 语句间歇性地吐出垃圾:许多特殊字符和来自其他完全不相关的 cout 语句的一点点。发生这种情况有什么特殊原因吗?

【问题讨论】:

  • 只有bottlePOD 类型时才有效。 bottle 是如何定义的?
  • 哦,真的吗? Bottle 绝对不是 POD:它具有私有和受保护的数据成员以及公共成员函数。那我就不能用fwrite了吗?
  • 你可以,但你不会从中得到任何有意义的东西......虽然你不应该遇到崩溃
  • 你能提供一个小而完整的例子来说明这个问题吗?
  • I can't attach the source code because <excuse> Always 表示您在调试期间没有创建 testcase,这意味着您不应该在这里询问。 :)

标签: c++ binaryfiles


【解决方案1】:

由于您的对象不是POD,因此您可以尝试写出它的所有成员。例如,

#include <fstream>

using namespace std;

class B
{
public:
    // Simple constructor
    B(int mem1, char mem2) : member1(mem1), member2(mem2) {}

    // Have some methods here
    bool write() const {
      fstream file("Bottle.dat", ios::out|ios::binary);
      if(!file.is_open())
        return false;
      file.write(reinterpret_cast<const char*>(&member1), sizeof(int));
      file.write(&member2, sizeof(char));
      file.close();
      return true;
    }

private:
    int member1;
    char member2;
};

int main()
{
  B sample(52, 'c');
  sample.write();
  return 0;
}

现在你可以打电话给yourobj.write(),它可以写信给Bottle.dat。您可以随心所欲地写出/编码您的数据。但这是一个简单的直接输出。您的前 4 个字节(嗯,sizeof(int) 字节)将是 member1,而您的下一个字节是 member2。因此,如果您愿意,也可以轻松阅读这种格式。

编辑

我已更新我的代码以使其成为可编译的示例。您可以使用十六进制编辑器观察输出文件以验证一切是否正确。您应该能够(在任何编辑器中)能够明显地看到对应于member2char ('c')。如果您在十六进制编辑器中打开它,您将看到前 4 个字节等于数字0x34。根据您机器的字节序,它可能看起来像 0000003434000000 这是十进制的 52,这是我们根据我的示例代码所期望的。

【讨论】:

  • 这看起来很有希望。但是当我编译时,我现在遇到了很多错误。我的目录好像没有包含stdbool.h,所以我把bool返回类型改成int,false改成0,true改成1。另外,它说file.open()中的参数不够,所以我做了变化。我的代码现在显示:fstream 文件; if (!file.open ("Bottle.dat",ios::out)) ... 但是它说 if 语句不是允许的类型。此外,对于 file.write 部分,它表示找不到与给定参数列表匹配的 ostream::write。我可能缺少头文件吗?
  • @Galena 抱歉 - 该示例不一定可编译。我已对其进行了更新,因此您可以复制/粘贴此代码并查看其执行情况。
  • 您会以二进制形式读取文件。您将读取sizeof(int) 的字节数并将其转换为int。也就是说,如果您正在处理二进制文件,您还需要一种方法来检查您的机器的字节序与文件的字节序,以了解如何解释您读入的这 4 个字节。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-24
  • 1970-01-01
  • 2018-12-01
  • 1970-01-01
相关资源
最近更新 更多