删除文件的任意块

时间:2010-08-21 23:56:57

标签: python c file-io

在开始和结束偏移的情况下,删除文件的任意块的最有效方法是什么?我更喜欢使用Python,但如果必须的话,我可以回到C.

说文件是这个

..............xxxxxxxx----------------

我想删除一大块:

..............[xxxxxxxx]----------------

手术后应该成为:

..............----------------

将整个事物读入内存并在内存中操作它不是一个可行的选择。

3 个答案:

答案 0 :(得分:4)

通过编写新版本的文件,然后以原子方式编写旧版本,几乎总能获得最佳性能,因为文件系统针对此类顺序访问进行了强烈优化,底层硬件也是如此(可能的例外情况)一些最新的SSD,但是,即使这样,它也是一个不确定的命题)。此外,这可以避免在系统崩溃的情况下随时销毁数据 - 您可以保留旧版本的文件,也可以保留新版本的文件。由于每个系统可能总是在任何时候崩溃(并且通过墨菲定律,它将选择最不幸的时刻;-),数据的完整性通常被认为非常重要(通常数据比系统更有价值)保留它 - 因此,“镜像”RAID解决方案以确保防止磁盘崩溃丢失宝贵的数据; - )。

如果你接受这种理智的方法,一般的想法是:打开旧文件进行阅读,新文件用于写作(创作);将N1个字节从旧文件复制到新文件;然后跳过旧文件的N2个字节;然后复制剩下的;关闭这两个文件;原子地重新命名为old。 (Windows显然没有可用于Python的“原子重命名”系统调用 - 为了在这种情况下保持完整性,而不是原子重命名,你要做三步:将旧文件重命名为备份名称,将新文件重命名为old,删除备份命名文件 - 如果在这三个非常快速的操作中的第二个中发生系统崩溃,则只需重命名一次即可恢复数据完整性。

N1和N2当然是两个参数,说明删除的片段的开始位置,以及它的长度。对于打开文件的部分,with open('old.dat', 'rb') as oldf:with open('NEWold.dat', 'wb') as newf:语句相互嵌套,显然是最好的(其余代码,直到重命名步骤必须嵌套在它们中)。

对于“复制其余部分”步骤,shutil.copyfileobj最好(确保指定一个缓冲区长度可以适应您的可用内存,但一个将倾向于提供更好的表现)。 “跳过”步骤显然只是seek打开阅读文件对象的oldf。为了从oldf到newf准确地复制N1个字节,Python的标准库中没有直接的支持,所以你必须编写自己的,例如:

def copyN1(oldf, newf, N1, buflen=1024*1024):
    while N1:
      newf.write(oldf.read(min(N1, buflen)))
      N1 -= buflen

答案 1 :(得分:0)

我建议memory mapping。虽然它实际上是在内存中操作文件,但是将整个文件简单地读入内存会更有效。

好吧,你必须以某种方式操作内存中的文件内容,因为在* nix和Win中都没有系统调用这样的操作(至少不是我知道的)。

答案 2 :(得分:0)

尝试mmap该文件。这不一定会一次性全部读入内存。

如果您真的想手动完成,请选择一些块大小并进行来回读写。但寻求会杀了你......