如何将大部分原始文件系统复制到文件中?
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
复制是行不通的。 (我假设)无法指定结束位置,因此复制不会停止。
这里有一些问题,每个问题都可以解决这个问题:
- 是否有采用 start/end 字节参数的复制库(或适用于 Windows 7 的外部实用程序,可与
subprocess
一起使用)?
- 是否可以创建一个
copyfileobj
可以使用的类文件对象,它只引用另一个类文件对象的一部分?
- 当
io
对象超过某个终点时是否会抛出异常?
- 能否
copyfileobj
强制自然停止在驱动器的给定字节偏移处(一种"fake EOF")?
最明显的方法是 write
到文件。
copyfileobj
的全部意义在于它为您缓冲数据。如果您必须将整个文件读入 BytesIO
,您只是在缓冲 BytesIO
,这是毫无意义的。
所以,只需循环 read
从 src_f
和 write
到 dst_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)
我正在使用神秘的数据收集文件系统。它有一个描述文件及其在磁盘上的确切偏移量的块,所以我知道每个文件的起始字节、结束字节和字节长度。目标是从物理磁盘中抓取一个文件。它们是大文件,因此性能至关重要。
这是 "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
复制是行不通的。 (我假设)无法指定结束位置,因此复制不会停止。
这里有一些问题,每个问题都可以解决这个问题:
- 是否有采用 start/end 字节参数的复制库(或适用于 Windows 7 的外部实用程序,可与
subprocess
一起使用)? - 是否可以创建一个
copyfileobj
可以使用的类文件对象,它只引用另一个类文件对象的一部分? - 当
io
对象超过某个终点时是否会抛出异常? - 能否
copyfileobj
强制自然停止在驱动器的给定字节偏移处(一种"fake EOF")?
最明显的方法是 write
到文件。
copyfileobj
的全部意义在于它为您缓冲数据。如果您必须将整个文件读入 BytesIO
,您只是在缓冲 BytesIO
,这是毫无意义的。
所以,只需循环 read
从 src_f
和 write
到 dst_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)