如何将大部分原始文件系统复制到文件中?

How to copy a large portion of a raw filesystem to a file?

我正在使用神秘的数据收集文件系统。它有一个描述文件及其在磁盘上的确切偏移量的块,所以我知道每个文件的起始字节、结束字节和字节长度。目标是从物理磁盘中抓取一个文件。它们是大文件,因此性能至关重要。

这是 "works," 但效率很低的方法:

import shutil, io
def start_copy(startpos, endpos, filename="C:\out.bin"):
    with open(r"\.\PhysicalDrive1", 'rb') as src_f:
        src_f.seek(startpos)
        flength = endpos - startpos
        print("Starting copy of "+filename+" ("+str(flength)+"B)")
        with open(filename, 'wb') as dst_f:
            shutil.copyfileobj( io.BytesIO(src_f.read(flength)), dst_f )
        print("Finished copy of "+filename)

这很慢:io.BytesIO(src_f.read(flength)) 技术上可行,但它会在写入目标文件之前将整个文件读入内存。所以它花费的时间比应该的长得多。

直接使用dst_f复制是行不通的。 (我假设)无法指定结束位置,因此复制不会停止。

这里有一些问题,每个问题都可以解决这个问题:

最明显的方法是 write 到文件。

copyfileobj 的全部意义在于它为您缓冲数据。如果您必须将整个文件读入 BytesIO,您只是在缓冲 BytesIO,这是毫无意义的。

所以,只需循环 readsrc_fwritedst_f 的 decent-sized 缓冲区,直到到达 flength字节。

如果你看the shutil source (which is linked from the shutil docs),里面没有魔法copyfileobj;这是一个微不足道的功能。从 3.6 开始(我认为自从在 2.1 左右添加了 shutil 之后它就完全没有变化了……),它看起来像这样:

def copyfileobj(fsrc, fdst, length=16*1024):
    """copy data from file-like object fsrc to file-like object fdst"""
    while 1:
        buf = fsrc.read(length)
        if not buf:
            break
        fdst.write(buf)

您可以做同样的事情,只跟踪读取的字节并停止在 flength:

def copypartialfileobj(fsrc, fdst, size, length=16*1024):
    """copy size bytes from file-like object fsrc to file-like object fdst"""
    written = 0
    while written < size:
        buf = fsrc.read(min(length, size - written))
        if not buf:
            break
        fdst.write(buf)
        written += len(buf)