写入和读取.dat文件C ++的记录

时间:2012-05-04 14:32:59

标签: c++ file-io record

我是C ++的新手,我正在尝试研究如何将以下结构格式的记录写入文本文件:

struct user {
    int id;
    char username [20];
    char password [20];
    char name [20];
    char email [30];
    int telephone;
    char address [70];
    int level;
}; 

到目前为止,我能够写得很好,但没有增加的id号,因为我不知道如何计算记录的数量,所以在我将数据写入之后文件看起来像这样文件。

1 Nick pass Nick email tele address 1
1 user pass name email tele address 1
1 test test test test test test 1
1 user pass Nick email tele addy 1
1 nbao pass Nick email tele 207 1

使用以下代码:

ofstream outFile;

outFile.open("users.dat", ios::app);

// User input of data here

outFile << "\n" << 1 << " " << username << " " << password << " " << name << " "
        << email << " " << telephone << " " << address  << " " << 1;
cout << "\nUser added successfully\n\n";

outFile.close();

那么,如何在插入时增加每条记录的值以及如何在文件中定位特定记录?

编辑:我已经能够显示每一行:

  if (inFile.is_open())
    {
    while(!inFile.eof())
    {

    cout<<endl;
    getline(inFile,line);
    cout<<line<<endl;

    }
    inFile.close();
    }

6 个答案:

答案 0 :(得分:1)

使用典型方法至少你需要使用修复大小记录,如果你想在阅读文件时有随机访问权限,那么说你有5个字符的名称它将被存储为

bob\0\0

或用于填充的任何其他内容,这样您就可以使用记录号*记录大小进行索引。

要以您的方式递增索引,您需要读取文件以查找高现有索引并递增它。或者您可以将文件加载到内存中并附加新记录并将文件写回

std::vector<user> users=read_dat("file.dat");
user user_=get_from_input();
users.push_back(user_);

then write the file back
std::ofstream file("file.dat");
for(size_t i=0; i!=users.size(); ++i) {
    file << users.at(i); 
   //you will need to implement the stream extractor to do this easily
}

答案 1 :(得分:1)

到目前为止你所拥有的并不坏,除了它无法处理你的字符串中有空格的情况(例如在地址中!)

您要做的是编写一个非常基础的数据库。您需要三个需要单独实施的操作(尽管在某些情况下交织它们可能会给您带来更好的性能,但我确信这不是您的关注点。)

  • 插入:您已经实现了此功能。您可能想要更改的内容是" ""\n"。这样,struct的每个字段都在一个新行中,并解决了空格问题。稍后阅读时,您需要逐行阅读
  • 搜索:要搜索,您需要打开文件,按结构读取struct(它本身包括读取与您的struct字段对应的许多行)并标识您感兴趣的实体。如何处理它们是另一个问题,但最简单的情况是返回数组(或向量)中匹配实体的列表。
  • 删除:这与搜索类似,但您必须重写文件。你所做的基本上是,再次按结构读取结构,看看哪些符合你的删除标准。您忽略那些匹配,并将其余部分写入(如插入部分)另一个文件。之后,您可以使用新文件替换原始文件。

这是一个伪代码:

Write-entity(user &u, ofstream &fout)
    fout << u.id << endl
         << u.username << endl
         << u.password << endl
         << ...

Read-entity(user &u, ifstream &fin)
     char ignore_new_line
     fin >> u.id >> ignore_new_line
     fin.getline(u.username, 20);
     fin.getline(u.password, 20);
     ...
     if end of file
         return fail

Insert(user &u)
     ofstream fout("db.dat");
     Write-entity(u, fout);
     fout.close();

Search(char *username) /* for example */
     ifstream fin("db.dat");
     user u;
     vector<user> results;
     while (Read-entity(u))
         if (strcmp(username, u.username) == 0)
             results.push_back(u);
     fin.close();
     return results;

Delete(int level) /* for example */
     ifstream fin("db.dat");
     ofstream fout("db_temp.dat");
     user u;
     while (Read-entity(u))
         if (level != u.level)
             Write-entity(u, fout);
     fin.close();
     fout.close();
     copy "db_temp.dat" to "db.dat"

附注:在写完数据之后放置\n是个好主意(这样你的文本文件就会end in a new line

答案 2 :(得分:1)

我建议将文件处理程序包装到一个Class中,然后为你的struct重载操作符>> and <<,这样你就可以控制进出了。 例如

struct User{
...
};

typedef std::vector<User> UserConT;

struct MyDataFile
{
  ofstream outFile;
  UserConT User_container;

  MyDataFile(std::string const&); //
  MyDataFile& operator<< (User const& user); // Implement and/or process the record before to write
  MyDataFile& operator>> (UserConT & user); // Implement the extraction/parse and insert into container
  MyDataFile& operator<< (UserConT const & user); //Implement extraction/parse and insert into ofstream 
};

MyDataFile& MyDataFile::operator<< (User const& user)
{
  static unsigned myIdRecord=User_container.size();
  myIdRecord++;
  outFile << user.id+myIdRecord << ....;
  return *this;
}



int main()
{
   MydataFile file("data.dat");

   UserConT myUser;
   User a;
   //... you could manage a single record  
   a.name="pepe"; 
   ...
   file<<a;
   ..//

}

答案 3 :(得分:0)

.Dat文件通常是一个简单的文本文件,可以使用记事本打开。因此,您只需读取文件的最后一行,读取它,提取第一个字符,将其转换为整数。然后递增值并完成。 这里有一些示例代码:

  #include <iostream.h>
  #include <fstream.h>
  using namespace std;

  int main(int argc, char *argv[])
  {
    ifstream in("test.txt");

  if(!in) {
       cout << "Cannot open input file.\n";
       return 1;
    }

     char str[255];

     while(in) {
       in.getline(str, 255);  // delim defaults to '\n'
        //if(in) cout << str << endl;
     }
    // Now str contains the last line , 
    if  ((str[0] >=48) || ( str[0] <=57))
    {
      int i = atoi(str[0]);
      i++;
    } 
    //i contains the latest value , do your operation now
    in.close();

     return 0;
     }

答案 4 :(得分:0)

假设您的文件格式不需要是人类可读的。

您可以将结构写入文件,例如。

outFile.open("users.dat", ios::app | ios::binary);
user someValue = {};
outFile.write( (char*)&someValue, sizeof(user) );

int nIndex = 0;
user fetchValue = {};
ifstream inputFile.open("user.data", ios::binary);

inputFile.seekg (0, ios::end);

int itemCount = inputFile.tellg() / sizeof(user);

inputFile.seekg (0, ios::beg);

if( nIndex > -1 && nIndex < itemCount){
    inputFile.seekg ( sizeof(user) * nIndex , ios::beg);
    inputFile.read( (char*)&fetchValue, sizeof(user) );
}

答案 5 :(得分:0)

写入文件的代码是用户结构的成员函数? 否则,我看到输出和结构之间没有任何关联。

可能的事情:

  • 编写id成员而不是1
  • 使用id的计数器并在每次写入时递增它
  • 不写id,读取时使用行号作为id