将std :: string插入std :: fstream中的任意位置

时间:2011-10-25 16:36:37

标签: c++ file-io stl fstream

我有一个Visual Studio 2008 C ++应用程序,我希望使用std::fstream将字符串插入文件中的任意点。该文件的大小可能大到100MB,因此我不想将其完全读入内存,修改它并重新写入新文件。

/// Insert some data in to a file at a given offset
/// @param file stream to insert the data
/// @param data string to insert
/// @param offset location within the file to insert the data
void InsertString( std::fstream& file, const std::string& data, size_t offset );

我现在正在考虑的方法是读取文件,将每个字节从末尾反向移出数据字符串的长度,然后插入新字符串。

实现这一目标的最有效方法是什么?

3 个答案:

答案 0 :(得分:3)

您刚刚提到了数据库格式的基本动机之一,以及它们的实现需求。

基于此,解决方案似乎非常明显,至少对我而言:您需要使用某种数据库格式,可能还有直接支持该格式的代码。几乎任何不错的数据库格式都会支持你所说的所需,所以主要是决定哪个代码库提供你喜欢的界面。

当然,如果您需要生成(例如)正常的文本文件作为结果,那么这不是一个真正的解决方案。对于这样的情况,你几乎需要咬紧牙关,并且需要复制大量数据。至少根据我的经验,操作系统完全面向顺序读取文件,除非你的修改完全接近文件的末尾,否则你可能很容易发现读取和写入整个文件的效率更高而不是复制足够的空间来为新数据腾出空间。

答案 1 :(得分:2)

除非这是极其罕见的操作,否则不要。强烈重新考虑您的文件格式,因此您不必在中间插入字符串,因为您怀疑必须将数据向下移动并且在大文件中如果您正在做很多事情,这将不会非常有效。

如果这种情况非常罕见,那么我会说只需读取旧文件到插入点,然后编写新文件,编写新字符串,然后从旧文件中读取/写入。最后,删除旧文件并重命名新文件。

答案 2 :(得分:0)

您可以使用Seekp将文件指针移动到所需的药水。但是您需要使用GetFileSize()之类的东西来了解文件大小。无论哪种方式,您都需要在插入点之后读取所有数据以将其写入新文件。如果内存消耗是主要的话,我会读取一个块并写一个块,或者如果性能是主要问题则使用内存映射文件并允许操作系统处理缓冲。