C++随机访问文件

C++ Random Access Files

本文关键字:文件 访问 随机 C++      更新时间:2023-10-16

这是我第一次在C++中尝试随机访问文件,但是,我以前在 Java 中尝试过,但我无法让它在C++中工作。这个想法是我想创建 100 条空记录,然后在文件中的特定记录号处存储一条记录。这是我的代码,我尽可能保持简单。

我这里有一个名为工具的结构:

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

这是我在主函数中拥有的内容:

fstream outFile;
outFile.open("inventory.dat");
// Create 100 empty tool records
Tool tool;
tool.number = 0;
tool.name[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();

我初始化 100 条空记录的部分工作正常(假设我们要注释代码的插入部分。

但是,当执行插入部分时,我的程序会生成 4 GB 的数据。我不确定发生了什么。我感谢任何形式的帮助。提前谢谢。

你可以写结构的全部内容

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

不要忘记告诉编译器不要插入填充

#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

来源:

https://codereview.stackexchange.com/questions/26344/writing-reading-data-structure-to-a-file-using-c
https://stackoverflow.com/a/18654265/194717我们宝贵成员的评论。

你在最后一部分的意思是t使用了tool。特别:

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

应该是:

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

以及末尾的所有其他tool.字段(假设您要使用 t )。 此时tool.number为 0,因此tool.number - 1为 -1。如果pos_type是无符号的 32 位,则包装的值将请求的位置置于 4GB 左右。

此外,托马斯·马修斯(Thomas Matthews)在他的评论中提出的对齐点以及托尼(Tony)在他的回答中详细说明的对齐点对于确保文件中的数据正确也很重要。

重复数据删除器和Galik在关于二进制模式的评论中提出的观点对于确保正确写入数据也很重要。

这是一个替代方案:

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.datn";
    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 readingn";
    return 2;
  }
  in_file.seekg(10 * t.binary_size(), ios::beg);
  t.binary_read(in_file);
  return 0;
}  

这里的概念是将读取和写入函数放入对象中,因为对象知道其成员,并且您可以对其他对象隐藏数据(一件好事)。