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

时间:2019-03-13 18:55:16

标签: c++ c++17 xcode10

所以基本上我试图在.dat文件中保存一个类,但是在我的代码中,但是它表示此错误没有匹配的成员函数来调用“ open”,但是我放了fstream标头。我不知道我写错了什么。我使用Xcode10。

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));




}

4 个答案:

答案 0 :(得分: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作为long int(在那里没有问题)
  • memberid作为一个整数(在那里没有问题)
  • name.size作为size_t
  • name.dataname.size个字节

答案 1 :(得分: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;
}

答案 2 :(得分: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. 
    ...
}

答案 3 :(得分:-1)

以上答案解决了您的最初问题。我将再谈两个。

首先,您可能应该在方法末尾使用f.close()。让它脱离作用域并从那里清理可能是完全好的,但是我个人认为这很丑陋,我不会指望它。

第二,除非确实有充分的理由,否则我不会以二进制形式存储数据。它不会是便携式的。上面的Serge建议使用序列化方法。我会考虑另一种方法。我会以人类可读的形式(例如JSON)写入文件。是的,还有很多工作,但是...

-如果您更改班级,仍然可以读取旧文件 -它们可跨环境移植 -您实际上可以查看它们并轻松了解它们包含的内容

因此Serge的上述建议并不可怕,但我会选择更现代的序列化/反序列化样式。

请注意,您的f.write无法使用,因为您的对象包含其他对象,您不知道它们在后台如何工作。例如,该字符串几乎肯定不能以您尝试的方式转储。另外,您不仅要转储数据。

此外,您应该打印f sizeof(k)。您可能会发现有趣的信息。尝试考虑每个字节。您可以打印出sizeof(k.name)来帮助您解决其中的一些问题。

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