是否可以在不重写的情况下将数据添加到文件中?

Posted

技术标签:

【中文标题】是否可以在不重写的情况下将数据添加到文件中?【英文标题】:Is it possible to prepend data to an file without rewriting? 【发布时间】:2011-01-30 17:18:11 【问题描述】:

我处理非常大的二进制文件(每个文件数 GB 到数 TB)。这些文件以旧格式存在,升级需要将标头写入文件的前面。我可以创建一个新文件并重写数据,但有时这可能需要很长时间。我想知道是否有更快的方法来完成此升级。该平台仅限于 Linux,我愿意使用低级函数(ASM、C、C++)/文件系统技巧来实现这一点。主库是 Java,JNI 完全可以接受。

【问题讨论】:

所有答案都证实了我已经知道的。只是希望有一些我不知道的魔法。感谢您提供额外的脑力。 【参考方案1】:

本机没有通用的方法。

也许某些文件系统提供了一些功能来执行此操作(无法给出任何提示),但您的代码将依赖于文件系统。


解决方案可以是模拟一个文件系统:您可以将数据存储在一组文件中,然后提供一些函数来打开、读取和写入数据,就好像它是一个文件。

【讨论】:

+1 使用建议的解决方案,标头可以作为旧文件旁边的文件存在,具有不同的后缀或扩展名。如果要打开的文件被检测为遗留文件,文件系统抽象将自动访问头文件。【参考方案2】:

听起来很疯狂,但如果可以更改从文件读取数据的函数,您可以按相反的顺序存储文件数据。在这种情况下,您可以在文件末尾附加数据(以相反的顺序)。这只是一个普遍的想法,所以我不能推荐任何特别的东西。 当前文件的反转代码如下所示:

 std::string records;
 ofstream out;
std::copy( records.rbegin(), records.rend(), std::ostream_iterator<string>(out));

【讨论】:

好主意,但这需要反转初始文件写入(以及附加)。所以这个想法只适用于现有文件,即使这样,也需要完全重写(以相反的顺序)。【参考方案3】:

这取决于您所说的“文件系统技巧”是什么意思。如果您愿意使用文件系统的磁盘格式,并且您要添加的标头大小是文件系统块大小的倍数,那么您可以编写直接操作文件系统的磁盘结构的程序(卸载文件系统)。

这家企业虽然听起来很麻烦 - 如果您有数百个这样的巨型文件要处理,这可能才值得。

【讨论】:

【参考方案4】:

我会使用标准的 Linux 工具来完成。 编写另一个应用程序来执行此操作似乎不是最佳选择。

cat headerFile oldFile > tmpFile && mv tmpFile oldFile

【讨论】:

我认为 OP 正在寻找不需要重写整个文件的东西(就像你不需要重写它来附加一些数据一样)。如果headerFile 是 1 字节,oldFile 是 10GB,您的命令将花费大量时间。 @peoro:我意识到这就是 OP 想要的。但是为了使 FS 普遍高效,它们不会那样工作。作为设计权衡,它们对于常见功能非常有效,但对于不太常见的操作则效率低下。【参考方案5】:

我知道这是一个老问题,但我希望这对将来的人有所帮助。类似于模拟文件系统,您可以简单地使用命名管道:

mkfifo /path/to/file_to_be_read
 echo "HEADER"; cat /path/to/source_file;  > /path/to/file_to_be_read

然后,您针对 /path/to/file_to_be_read 运行旧程序,输入将是:

HEADER
contents of /path/to/source_file
...

只要程序按顺序读取文件并且不通过缓冲区进行mmap()rewind(),这将起作用。

【讨论】:

以上是关于是否可以在不重写的情况下将数据添加到文件中?的主要内容,如果未能解决你的问题,请参考以下文章

在不调用 save 的情况下将对象添加到数据库

是否可以在不使用 QLayout 的情况下将 pyqtgraph 添加到 PySide 应用程序?

是否可以在不运行 QEMU 的情况下将文件复制到 QEMU 映像?

SSAS - 是不是可以在不重新部署整个多维数据集的情况下将属性添加到现有维度

如何在不覆盖以前数据的情况下将数据添加到 XML 文件(C#)

如何在不覆盖现有记录的情况下将新行添加到数据表