代码之家  ›  专栏  ›  技术社区  ›  charjabug

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

  •  1
  • charjabug  · 技术社区  · 6 年前

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

    以下是“有效”但效率很低的方法:

    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 行不通。(我假设)无法指定结束位置,因此复制不会停止。

    以下是一些问题,每个问题都可以解决:

    • 是否有可用于 subprocess )是否接受开始/结束字节参数?
    • 是否可以创建一个类似文件的对象 copyfileobj 可以使用,它只引用另一个类似文件的对象的一部分?
    • io 对象寻求超过某个终点?
    • 可以 copyfileobj 被迫在驱动器的给定字节偏移量(一种“伪EOF”)处自然停止?
    1 回复  |  直到 6 年前
        1
  •  2
  •   abarnert    6 年前

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

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

    所以,绕个圈子 read 正在从 src_f it收件人 dst_f 直到你到达 flength 字节。

    如果你看 the shutil source (链接自 the shutil docs ),里面没有魔法 copyfileobj ;这是一个微不足道的函数。从3.6开始(我认为从那时起它就完全没有变化 舒蒂尔 是在2.1左右添加的),看起来像这样:

    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)
    

    您可以做同样的事情,只需跟踪读取的字节并在 FLENGHT公司 :

    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)