【问题标题】:debug read/write string to binary file调试读/写字符串到二进制文件
【发布时间】:2014-01-03 04:56:17
【问题描述】:

我正在尝试写入二进制文件,这是我的 sn-p 代码

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

struct user
{
    string ID;
    string password;    
};

int main()
{
    fstream afile;
    afile.open("user.dat",ios::out|ios::binary);

    user person;

    person.ID ="001";

    person.password ="abc";

    afile.write (reinterpret_cast <const char *>(&person), sizeof (person));

    person.ID ="002";

    person.password ="def";

    afile.write (reinterpret_cast <const char *>(&person), sizeof (person));

    afile.close();

    afile.open("user.dat",ios::in|ios::binary);


    while (afile.read (reinterpret_cast <char *>(&person), sizeof (person)))
    {
        cout<<person.ID
            <<" "
            <<person.password
            <<endl;

    }

}

我希望我的控制台输出是

001 abc
002 def

相反,我得到了

002 def 
002 def

谁能给我解释一下?

【问题讨论】:

  • 在完成文件后关闭文件总是一个好主意,例如第二次打开 afile
  • @JonnyHenly,析构函数将其关闭。
  • 这行不通。 std::string 不是普通的旧数据对象,您不能以这种方式将它们转储到文件中或从文件中转储。改为查看序列化
  • 请注意std::string 内部有一个指针,您正在写入和读取该指针,而不是字符串。

标签: c++ debugging file-io binary binaryfiles


【解决方案1】:

std::string 是一个类,它的对象不直接存储字符串的内容。

它是为您的案例定义的实现,为简单起见,您可以这样理解:

std::string 有一个存储指向实际数据的指针(比如 ptr)的成员。

   std::string s = "001";

不会将ptr指向地址字符串“001”;它会分配内存并将字符串复制到该内存中。 那么当你这样做时

    s = "002";

它不需要重新分配内存来存储“002”;它只是将“002”复制到之前存储“001”的内存中。

这意味着,如果你转储字符串的原始数据,它不会改变。

当你读回字符串原始数据时,它只会恢复指向“002”的指针

希望这会有所帮助。

【讨论】:

  • 请说如何解决它。
【解决方案2】:

不幸的是,你不能这么简单地做到这一点,因此你只写了一个指向 std::string 的指针,而不是 string 包含的内容。您可以通过这种方式将字符串写入二进制文件:

afile.open("user.dat",ios::out|ios::binary);

user person;

person.ID ="001";
person.password ="abc";

int len = person.ID.size();
afile.write(reinterpret_cast<char*>(&len), sizeof(len));
afile.write(const_cast<char*>(person.ID.c_str()), len);

len = person.password.size();
afile.write(reinterpret_cast<char*>(&len), sizeof(len));
afile.write(const_cast<char*>(person.password.c_str()), len);

person.ID ="002";
person.password ="def";

afile.close();

这样你就可以阅读

afile.open("user.dat",ios::in|ios::binary);

afile.read(reinterpret_cast<char*>(&len), sizeof(len));
person.ID.resize(len);
afile.read(const_cast<char*>(person.ID.c_str()), len);

afile.read(reinterpret_cast<char*>(&len), sizeof(len));
person.password.resize(len);
afile.read(const_cast<char*>(person.password.c_str()), len);

cout << person.ID << " " << person.password << endl;

【讨论】:

    【解决方案3】:

    您正在存储struct 的原始数据,事实上,它只包含指针。这就是std::string 用于存储数据以使字符串可调整大小的方式。您的程序确实打印任何数据的唯一原因是在读取的那一刻,对象person 仍然存在。如果你把程序的读取部分放到一个单独的程序中,你将无法读取任何数据。

    要实际使用fstream 存储数据,您可以每行存储一个字符串,例如:

    afile << person.ID << endl;
    afile << person.password << endl;
    

    文件user.dat

    001
    abc
    002
    def
    

    你可以这样读:

    afile >> person.ID >> person.password;
    while (afile.good())
    {
      cout<<person.ID
      <<" "
      <<person.password
      <<endl;
      afile >> person.ID >> person.password;    
    }
    

    您还应该检查Serializing a class which contains a std::string

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-28
      相关资源
      最近更新 更多