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


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


3870
2018-01-30 17:18


起源

所有的答案都证实了我已经知道的事情。只是希望有一些我不知道的魔法。感谢额外的脑力。 - basszero


答案:


本机没有通用的方法。

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


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


9
2018-01-30 17:29



+1使用建议的解决方案,标头可以作为旧文件旁边的文件存在,具有不同的后缀或扩展名。如果要打开的文件被检测为旧文件,则文件系统抽象将自动访问头文件。 - Emile Cormier
将此标记为正确。必须确认怀疑。 - basszero


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

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

4
2018-01-30 18:53



好主意,但这需要反转初始文件写入(并附加)。因此,只有现有文件才能实现这一想法,即使这样,也需要完全重写(按相反的顺序)。 - Eugene Mayevski 'Allied Bits
+1在盒子外面思考 - sleske


这取决于你所说的“文件系统技巧”。如果你愿意对文件系统的磁盘格式不屑一顾,  要添加的标头大小是文件系统块大小的倍数,那么您可以编写一个程序来直接操作文件系统的磁盘结构(卸载文件系统)。

这个企业虽然听起来很毛茸茸 - 如果你有数百个这样的巨型文件要处理,它可能是值得的。


2
2018-01-31 00:39





我只是使用标准的Linux工具来做到这一点。
写另一个应用程序来做它似乎是次优的。

cat headerFile oldFile > tmpFile && mv tmpFile oldFile

0
2018-01-30 17:32



我认为OP正在寻找一些不需要重写整个文件的东西(就像你不需要重写它来附加一些数据一样)。如果 headerFile 是1个字节,和 oldFile 是10GB你的命令会花费很多时间。 - peoro
@peoro:我意识到这就是OP想要的。但是为了使FS普遍有效,他们不会那样工作。作为设计权衡,它们对于常见功能非常有效,但因此对于不太常见的操作而言效率低。 - Martin York


我知道这是一个老问题,但我希望这有助于将来的某个人。如同 模拟 一个文件系统,你可以简单地使用一个命名管道:

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() 过了缓冲区。


0
2017-08-15 20:34