在开始和结束偏移的情况下,删除文件的任意块的最有效方法是什么?我更喜欢使用Python,但如果必须的话,我可以回到C.
说文件是这个
..............xxxxxxxx----------------
我想删除一大块:
..............[xxxxxxxx]----------------
手术后应该成为:
..............----------------
将整个事物读入内存并在内存中操作它不是一个可行的选择。
答案 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
该文件。这不一定会一次性全部读入内存。
如果您真的想手动完成,请选择一些块大小并进行来回读写。但寻求会杀了你......