我正在编写一个程序,它可以同时从多个不同的服务器下载多个文件(当然,每个服务器一个下载线程!)。我担心磁盘上同时增长的多个文件会导致磁盘碎片,我想通过在磁盘上为完整文件的长度预分配空间来缓解这种情况(如 Content-Length
header 所报告的)在开始下载之前,最好不要增加文件的表观长度(这样我只需以追加模式打开部分下载的文件即可恢复失败的下载)。
这可以以独立于平台的方式实现吗?
最佳答案
我做了一些谷歌搜索,发现 this lovely article一些 C 代码可以完全满足您在 Windows 上的要求。以下是转换为 ctypes
的 C 代码(为了便于阅读而编写):
import ctypes
import msvcrt
# https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfileinformationbyhandle
set_file_information = ctypes.windll.kernel32.SetFileInformationByHandle
class AllocationInfo(ctypes.Structure):
_fields_ = [('AllocationSize', ctypes.c_longlong)]
def allocate(file, length):
"""Tell the filesystem to preallocate `length` bytes on disk for the specified `file` without increasing the
file's length.
In other words, advise the filesystem that you intend to write at least `length` bytes to the file.
"""
allocation_info = AllocationInfo(length)
retval = set_file_information(ctypes.c_long(msvcrt.get_osfhandle(file.fileno())),
ctypes.c_long(5), # constant for FileAllocationInfo in the FILE_INFO_BY_HANDLE_CLASS enum
ctypes.pointer(allocation_info),
ctypes.sizeof(allocation_info)
)
if retval != 1:
raise OSError('SetFileInformationByHandle failed')
这会将文件在磁盘上的大小:如文件资源管理器中所示更改为您指定的长度(加上元数据的几千字节),但保持大小:不变。
然而,在我用谷歌搜索的半个小时里,我还没有找到在 POSIX 上做到这一点的方法。 Fallocate() 实际上与您所追求的完全相反:它将文件的表观长度设置为您给定的长度,但将其分配为磁盘上的稀疏范围,因此写入多个同时文件仍然会导致碎片。 Windows 具有 POSIX 所缺乏的文件管理功能,这不是很讽刺吗?
我最希望被证明是错误的,但我认为这是不可能的。
关于python - 在Python中为文件预分配磁盘空间而不改变其大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63275794/