简体   繁体   English

C ++随机访问文件

[英]C++ Random Access Files

its my first time to experiment random access files in C++ however, I've tried it before in Java but I can't get it work in C++. 这是我第一次在C ++中尝试随机访问文件,但是我之前在Java中尝试过它,但无法在C ++中使用它。 The idea is I a want to create 100 empty records, and then store a record at a particular record number in the file. 我的想法是要创建100个空记录,然后将记录存储在文件中的特定记录编号处。 Here is my code, I kept it as simple as possible. 这是我的代码,我尽可能地简化了代码。

I have here a structure named Tool: 我这里有一个名为Tool的结构:

struct Tool {
    int number;
    char name[20];
    int quantity;
    double cost;
};

And here is what I have in the main function: 这是我的主要功能:

fstream outFile;
outFile.open("inventory.dat");

// Create 100 empty tool records
Tool tool;
tool.number = 0;
tool.name[0] = '\0';
tool.quantity = 0;
tool.cost = 0;  

for (int i = 0; i < 100; i++) {
    outFile.write(reinterpret_cast<char *>(&tool.number), sizeof(int));
    outFile.write(tool.name, sizeof(char)* 20);
    outFile.write(reinterpret_cast<char *>(&tool.quantity), sizeof(int));
    outFile.write(reinterpret_cast<char *>(&tool.cost), sizeof(double));
}

// Insert A tool record
Tool t;
t.number = 3;
t.quantity = 7;
t.cost = 57;
strcpy(tool.name, "Electric Sander");

outFile.seekp((tool.number - 1) * sizeof(Tool));
outFile.write(reinterpret_cast<char *>(&tool.number), sizeof(int));
outFile.write(tool.name, sizeof(char)* 20);
outFile.write(reinterpret_cast<char *>(&tool.quantity), sizeof(int));
outFile.write(reinterpret_cast<char *>(&tool.cost), sizeof(double));

outFile.close();

The part where I initialize 100 empty record works fine (assuming we are to comment to the insert section of the code. 我初始化100条空记录的部分工作正常(假设我们要注释代码的插入部分。

However, when the insert section is performed, my program generates 4 GB of data. 但是,当执行插入部分时,我的程序会生成4 GB的数据。 I'm not sure what's going on. 我不确定发生了什么。 I appreciate any kind of help. 我感谢任何帮助。 Thanks in advance. 提前致谢。

You could write the entire contents of the struct 您可以编写该结构的全部内容

    outFile.seekp(t.number*sizeof(Tool));
    outFile.write(reinterpret_cast<char *>(&tool),sizeof(Tool));

Don´t forget to tell the compiler to don´t insert the padding 不要忘记告诉编译器不要插入填充

#ifdef MSVC
#pragma pack(push,1)
#endif
struct Tool {
    int number;
    char name[20];
    int quantity;
    double cost;
#ifdef GCC
}__attribute__((packed));
#else
};
#endif

#ifdef MSVC
#pragma pack(pop)
#endif

Sources: 资料来源:
https://codereview.stackexchange.com/questions/26344/writing-reading-data-structure-to-a-file-using-c https://codereview.stackexchange.com/questions/26344/writing-reading-data-structure-to-a-file-using-c
https://stackoverflow.com/a/18654265/194717 https://stackoverflow.com/a/18654265/194717
Comments of our valuable members. 我们宝贵的成员的意见。

You used tool where you meant t in the last part. 您使用了在最后一部分中表示t tool In particular: 尤其是:

outFile.seekp((tool.number - 1) * sizeof(Tool));

Should be: 应该:

outFile.seekp((t.number - 1) * sizeof(Tool));

As well as all the other tool. 以及所有其他tool. fields at the end (presuming you want to use t ). 末尾的字段(假设您要使用t )。 tool.number at that point is 0, so tool.number - 1 is -1. tool.number为0,因此tool.number - 1为-1。 If pos_type is unsigned and 32-bits, the wrapped value puts your requested position at around 4GB. 如果pos_type是无符号且为32位,则包装的值会将您请求的位置放在4GB左右。

Also the alignment point Thomas Matthews brought up in his comment and Tony detailed in his answer is important to ensure that the data in the file is correct. 同样,托马斯·马修斯(Thomas Matthews)在其评论中提出的对准点和托尼(Tony)在其回答中详述的点对于确保文件中的数据正确也是很重要的。

The point Deduplicator and Galik raised in the comments regarding binary mode is also important to ensure that data is written correctly. 在有关二进制模式的注释中提到的Deduplicator和Galik点对于确保正确写入数据也很重要。

Here's an alternative: 这是一个替代方案:

struct Tool
{
    int number;
    char name[20];
    int quantity;
    double cost;
    void binary_write(std::ostream& out) const
    {
      out.write((char *) &number, sizeof(number));
      out.write((char *) &name[0], sizeof(name);
      out.write((char *) &quantity, sizeof(quantity));
      out.write((char *) &cost, sizeof(cost));
    }
    void binary_read(std::istream& inp)
    {
      inp.read((char *) &number, sizeof(number));
      inp.read((char *) &name[0], sizeof(name);
      inp.read((char *) &quantity, sizeof(quantity));
      inp.read((char *) &cost, sizeof(cost));
    }
    size_t binary_size(void) const
    {
      return sizeof(number) + sizeof(name)
             + sizeof(quantity) + sizeof(cost);
    }
};

int main(void)
{
  std::ofstream outfile("test.dat", ios::binary);
  if (!outfile)
  {
    cerr << "Error opening test.dat\n";
    return 1;
  }
  Tool t;
  for (unsigned int i = 0; i < 100; ++i)
  {
    t.binary_write(outfile);
  }
  outfile.close();
  std::ifstream in_file("test.dat", ios::binary)
  if (!in_file)
  {
    cerr << "Error opening test.dat for reading\n";
    return 2;
  }
  in_file.seekg(10 * t.binary_size(), ios::beg);
  t.binary_read(in_file);
  return 0;
}  

The concept here is to place the read and write functions into the object, because the object knows about its members and you can hide the data from other objects (a good thing). 这里的概念是将读写功能放入对象中,因为该对象了解其成员,并且您可以从其他对象中隐藏数据(这是一件好事)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM