在c ++中打开.dat文件时出现问题

问题描述 投票:0回答:4

所以基本上我试图在.dat文件中保存一个类,但在我的代码中,但它说这个错误没有匹配的成员函数调用'打开',但我把fstream标题。我不知道我是不是写错了。我使用Xcode 10。

class memberinformation
{
    string name; //name
    long int phonenumber; // phone number
    int memberid; // member id
    public :
    memberinformation()
    { name="not assigned" ;
        phonenumber=0;
        memberid=0;
    }
    int option3();
    int option2();
    int option1();
    int option4();
};



void wrt_file() //file function
{
    memberinformation k;
    fstream f;
    f.open ("information.dat",ios::app,ios::binary) //this is where I get the error. 
            f.write((char*)&k,sizeof(k));




}
c++ c++17 xcode10
4个回答
3
投票

你很幸运被一个简单的错误所阻止。 @ Alex44已经展示了如何摆脱错误:

f.open ("information.dat",ios::app|ios::binary); //this is where I get the error. 

但以下几行更糟糕:

f.write((char*)&k,sizeof(k));

因为编译器不会显示任何错误,而字符串的内容将不会保存在文件中。 std::string不是一成不变的,因此,memberinformation类也不是。因此,您不应该尝试将其作为原始字节写入文件。

您应该编写一个写入二进制流的序列化函数(只是一种可能的序列化方式):

  • phonenumber作为长整数(没有问题)
  • memberid作为一个int(没问题)
  • name.size作为size_t
  • name.dataname.size字节

2
投票

另外两个答案已经回答:

  1. Why its not compiling
  2. Why its a bad idea to write binary objects

我建议你通过使用流操作符的标准C ++技术序列化对象。这使得写入/读取对象变得微不足道,并且通常使调试问题变得容易。

使用@serge-ballesta在他的帖子中建议的格式:

class memberinformation
{
    string    name; //name
    long int  phonenumber; // phone number
    int       memberid; // member id
    public :
      // OLD STUFF GOES HERE

    void swap(memberinformation& other) noexcept
    {
         using std::swap;
         swap(name,        other.name);
         swap(phonenumber, other.phonenumber);
         swap(memberid,    other.memberid);
    }
    friend std::ostream& operator<<(std::ostream& str, memberinformation const& data)
    {
         return str << data.phonenumber << " "
                    << data.memberid    << " "
                    << data.name.size() << " "
                    << data.name        << " ";
    }
    friend std::istream& operator<<(std::istream& str, memberinformation& data)
    {
         memberinformation tmp;
         std::size_t       nameSize
         if (str >> tmp.phonenumber >> tmp.memberid >> nameSize) {
             // All sizes were read correctly.
             tmp.name.resize(nameSize);
             if (str.ignore(1).read(&tmp.name[0], nameSize)) {
                 // ignored the space and read the name correctly.
                 // So now we update the "data" object
                 tmp.swap(data);
             }
         }
         return str;
    }
};

现在在您的代码中:

int main()
{
    memberinformation   object;

    std::cout << object;
    std::cin  >> object;

    std::ofstream  file("Data.dat");
    file << object;
}

1
投票

你错过了一个分号,你需要“按位或”你的旗帜:

void wrt_file() //file function
{
    memberinformation k;
    fstream f;
    f.open ("information.dat",ios::app|ios::binary); //this is where I get the error. 
    ...
}

-1
投票

上面的答案解决了您的初始问题。我要谈两个以上。

首先,您可能应该在方法结束时使用f.close()。让它从研究范围中删除并从那里清理可能是完全正常的,但我个人认为这很难看,我不会指望它。

其次,我不会将数据存储在二进制中,除非有充分的理由去做。它不便携。上面的Serge建议采用序列化方法。我会考虑另一种方法。我用人类可读的形式(如JSON)写入文件。是的,这是一个更多的工作,但......

- 如果你改变你的课程,你的旧文件仍然是可读的 - 它们可以跨环境移植 - 你实际上可以查看它们并且很容易理解它们包含的内容

所以Serge的上述建议并不可怕,但我会选择更现代的序列化/反序列化风格。

请注意,您的f.write将无法工作,因为您的对象包含其他对象,您不知道它们是如何工作的。例如,这个字符串几乎肯定不会像你试图那样被抛弃。此外,您不仅会丢弃数据。

另外,你应该printf sizeof(k)。您可能会发现它有趣的信息。尽量考虑每个字节。你可以printf sizeof(k.name)来帮助你解决一些问题。

我几乎肯定这样做的信息会让你感到惊讶,但我自己并没有真正做到这一点,因为我永远不会尝试原始内存复制C ++对象,这实际上是你想要做的。

© www.soinside.com 2019 - 2024. All rights reserved.