2014-10-01 94 views
0

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

这是我救我的结构:

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

我不知道该怎么办,这甚至有可能吗?我玩弄了将结构标记为无效的想法,所以即使我的程序会读取它,它也不会将它用于任何事情,但再次,似乎是一个可怜的主意。

有什么建议吗?

+0

通常的解决方案是复制,跳过你不想复制的内容。但是你的阅读循环被破坏了;在使用结果之前,您不会验证您的读取是否成功。 (当然,如果你用这种方式写这个文件,几乎可以保证将来有一段时间,你将无法阅读它。) – 2014-10-01 17:20:28

回答

2

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

这里需要的是一些更多的参与。例如,你可以想出一个的系统标记一个结构为删除。您的代码需要在该位置写入一些特殊值,以便知道它已被删除,然后在保存另一个结构时重新使用该位置。

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

这种方法有许多变化。确切的代码需要一种取决于你的应用程序。

+0

我想我会用这个解决方案从众多的这里的答案,只是因为我认为它适合我的需要最好的。我会不断删除元素并将新的元素写入文件,这是一种耻辱,我不再能够在编写新元素时追加,但希望它能运行 – user3932479 2014-10-01 18:12:45

+0

如果正确实施,这条路线应该会给你最棒的表演。 – 2014-10-01 18:15:48

+0

@ user3932479如果你的结构体的大小都是固定的,顺序无关紧要,那么可以很容易地重新填充未使用的空间。 FWIW,mmap也同样适用于这种情况,根据我的经验,stdio或stream的性能改进是惊人的。 – Alnitak 2014-10-01 18:22:07

2

一个潜在的非常快速的方法,如果该文件不超过可用RAM较大的是使用mmap

  1. mmap文件
  2. 发现问题
  3. memmove一切结构的存储位置在该位置上方向下按结构尺寸
  4. munmap该文件。
  5. ftruncate文件到新的长度
0

我不知道如果我理解正确的话......不过,你可以得到该结构(找到它的二进制文件),复制所有字节,直到该位置,跳过下一个sizeof(该结构)字节,并将其余的二进制文件复制到该新文件?

0

假设所有struct s文件中是相同的尺寸和类型,顺序并不重要,这里的算法是什么样子:

  1. 找到struct被删除,请记住它的位置
  2. 查找文件
  3. 复制最后一个struct最后struct的内容到由一个占用的空间将被删除
  4. 无论是垫文件或者我们结束E专用操作系统的功能(truncate()在Unix上,SetEndOfFile()在Windows上)

AFAIK有缩小文件的大小,所以你必须使用特定于平台的东西,对于部分没有与平台无关的方式。