在C ++中从二进制文件中删除struct

时间:2014-10-01 17:10:27

标签: c++ file struct

我目前正在尝试实现一个删除已保存在二进制文件中的特定结构的函数。我对如何去做有点困惑。我有一个可行但不是特别优雅的解决方案:我可以将整个结构文件读取到结构向量,删除旧文件,删除我想从向量中删除的结构,然后保存向量结构再次作为文件。我非常有信心这会起作用,但如果文件很大,它似乎是一个冗长而且可能不必要的解决方案。我知道如何找到我想要删除的结构,并且我知道如何更改它中的值(通过覆盖它),但我究竟可以删除它?

这是我保存结构的方式:

std::fstream binary_file(fileLocation.c_str(), std::ios::out | std::ios::binary | std::ios::app);
binary_file.write(reinterpret_cast<char *>(&myStruct), sizeof(myStruct));
binary_file.close();

每个结构都有一个带有唯一ID的整数,我用它来查找适当的结构,如下所示:

myStream.open(fileLocation.c_str(), std::ios::in | std::ios::out | std::ios::binary);
    while (!myStream.eof())
    {
        myStream.read(reinterpret_cast<char*>(&myStruct), sizeof(myStruct));
        if (myStruct.ID == given_ID)
        {
            temp_fstream.seekg(-(sizeof(myStruct), std::ios::cur);
            //delete struct
            return;
        }
    }

我不知道该怎么做,有可能吗?我已经玩弄了只是将结构标记为无效的想法,所以即使我的程序会读它也不会用它来做任何事情,但再次看来,这似乎是一个糟糕的主意。

有什么建议吗?

4 个答案:

答案 0 :(得分:2)

您可以在没有删除项目的情况下重新创建文件,但是效果非常低效。

这里需要的是更多涉及的东西。例如,您可以将标记结构的系统设为已删除。您的代码需要在该位置编写一些特殊值,以便它知道它已被删除,然后在保存另一个结构时重用该插槽。

这会增加代码的复杂性。您无法在一个语句中简单地读取和编写结构集合。

这种方法有很多变化。所需的确切代码取决于您的应用程序。

答案 1 :(得分:2)

如果文件不大于可用RAM,则可能非常快速的方法是使用mmap

  1. mmap文件
  2. 找到有问题的结构的内存位置
  3. memmove该位置之上的所有内容都按结构的大小缩小
  4. munmap文件。
  5. ftruncate文件到新的长度

答案 2 :(得分:0)

我不确定我是否理解正确...但是,你能不能到达那个结构(在二进制文件中找到它),复制所有字节直到那个位置,跳过下一个sizeof(那个struct)字节,并将二进制文件的其余部分复制到该新文件?!

答案 3 :(得分:0)

假设文件中的所有struct都是相同的大小和类型,并且顺序无关紧要,这就是算法的样子:

  1. 找到要删除的struct,记住其位置
  2. 查找文件中的最后一个struct
  3. 将最后struct的内容复制到要删除的内容所占用的空间
  4. 填充文件末尾或使用特定于操作系统的功能(在Unix上为truncate(),在Windows上为SetEndOfFile()
  5. AFAIK没有平台无关的方法来缩小文件的大小,因此您必须使用该部分的平台特定内容。