从文件中间移除内存

Remove memory from the middle of a file

本文关键字:内存 中间 文件      更新时间:2023-10-16

我有一个二进制格式,它是这样构建的:

magic number
name size blob
name size blob
name size blob
...

是为了方便地在文件中移动并找到正确的条目。但我也想删除一个条目(让我们称它为块,因为它是一个)。我想我可以使用std::copy/memmove和一些iostream迭代器将块移动到要删除的块后面,并将它们复制到要删除的块上。但是,我在最后删除的空间中填充了不可用的数据(我可以用零或不填满它)。之后我可能会收缩文件。

我知道我可以读取我想要保存在缓冲区中的所有数据并将其放入新文件中,但是我不喜欢为了删除一个块而重写整个文件。

有什么最好的删除文件中的数据的方法吗?

@MarkSetchell:我有一个好主意来威胁这个问题:

我现在在每个块的开头都有一个神奇的数字来检查是否有另一个有效的块来。在将一些数据移到开头之后,我将写入指针移到最后一个块的后面,并用零填充下一个神奇数字的空间。因此,当列出条目时,它将在没有有效的幻数时停止,如果我添加其他条目,它将自动覆盖未使用的空间。

我知道我可以读取我想要保存在缓冲区中的所有数据并将其放入新文件中,但是我不喜欢为了删除一个块而重写整个文件。

对于删除文件中的数据有什么最好的方法吗?

你不可能两全其美。如果你想保留空间,你需要一些东西来描述文件节(让我们称之为分配表),每个文件节由分片序列组成)。

一个section通常会开始(一个shard),但是一旦它被解分配,解分配的section将作为shard的一部分用于新section。现在可以选择在什么时间点使用分片(非连续)部分(可能只有在文件达到一定的大小限制之后)。

分配表将每个段描述为一个严重的(链接列表)分片(或一个分片,如果连续的话)。你可以为分配表保留一个固定的大小,或者把它放在一个不同的文件中,或者对它进行分片,并赋予它自我重构的能力。

struct Section
{
  struct Shard
  {
    std::size_t baseAddr_;
    std::size_t size_;
  };
  std::string name_;
  std::size_t shardCount_;
  std::vector<Shard> shards_;
  istream& readFrom( std::istream& );
};
struct AllocTable
{
  std::size_t sectionCount_;
  std::vector<Section> sections_;
  std::size_t next_;
  
  istream& readFrom( std::istream& is, AllocTable* previous )
  {
    //Brief code... error handling left as your exercise
    is >> sectionCount_;
    
    sections_.resize( sectionCount_ );
    for( std::size_t i = 0; i < sectionCount_; ++i ) 
    {
      sections_[i].readFrom( is );
    }
    is >> next_; //Note - no error handling for brevity
    if( next_ != static_cast<std::size_t>(-1) )
    {
      is.seekg( next_ ); //Seek to next_ from file beginning
      AllocTable nextTable;
      nextTable.readFrom( is, this );
      sections_.insert( sections_.end(), 
        nextTable.sections_.begin(), table_.sections_.end() );
    }
    return is;
  }
};