我有一个像这样的二进制格式:
magic number
name size blob
name size blob
name size blob
...
它可以轻松移动文件并找到正确的条目。但我还想删除一个条目(让它称之为一个块,因为它是一个)。我想我可以使用std :: copy / memmove和一些iostream迭代器来移动一个块后面的块来删除并将它们复制到上要删除的块。但后来我在最后删除的空间中填充了无法使用的数据(我可以用零填充它)。之后我可能会缩小文件。
我知道我可以读取我想要保存在缓冲区中的所有数据并将其放入新文件中,但我不喜欢重写整个文件以删除一个块。
有关最佳方法删除文件中数据的任何想法吗?
答案 0 :(得分:0)
@MarkSetchell:知道如何威胁这个问题:
我现在从每个块开始都有一个幻数,以检查是否有其他有效的块进入。在向开头移动一些数据之后,我将编写器指针移到最后一个块的后面,并用零填充下一个幻数的空间。因此,当列出条目时,它将在没有有效幻数时停止,如果我添加其他条目,它将自动覆盖未使用的空格。
答案 1 :(得分:0)
我知道我可以读取我想要保存在缓冲区中的所有数据并将其放入新文件中,但我不喜欢重写整个文件以删除一个块。
有关删除文件中数据的最佳方法的任何想法吗?
你不可能拥有两全其美的优势。如果你想保留空间,你需要一些东西来描述文件部分(让我们称之为分配表),每个文件部分由一系列分片组成。
一个部分将从正常开始(一个分片),但是一旦取消分配,取消分配的部分将作为新部分的分片的一部分可用。现在可以选择在哪个时间点您愿意使用分片(非连续)部分(可能仅在您的文件达到特定大小限制之后)。
分配表将每个部分描述为分片的严重(链接列表)(或者一个分片,如果是连续的)。可以为分配表保留固定大小,也可以将其放在不同的文件中,或者将其分解并赋予其重建自身的能力。
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;
}
};
...