C ++随机访问文件

时间:2014-11-13 01:29:03

标签: c++ file-io

这是我第一次用C ++实验随机访问文件,但是我以前在Java中尝试过但是我无法在C ++中使用它。我的想法是我想要创建100个空记录,然后将记录存储在文件中的特定记录号。这是我的代码,我尽可能简单。

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

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] = '\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的数据。我不确定发生了什么。我感谢任何帮助。提前谢谢。

3 个答案:

答案 0 :(得分:3)

您可以编写结构的全部内容

    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
我们有价值的成员的评论。

答案 1 :(得分:2)

您在最后一部分中使用tool表示t。特别是:

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)在他的comment中提出并且托尼在他的answer中详细说明,这对于确保文件中的数据是正确的非常重要。

Deduplicator和Galik在关于二进制模式的comments中提出的观点对于确保正确写入数据也很重要。

答案 2 :(得分:0)

这是另一种选择:

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

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