稀疏文件(英语:sparse file)是一种计算机文件,它能尝试在文件内容大多为空时更有效率地使用文件系统的空间。它的原理是以简短的信息(元数据)表示空数据块,而不是在在磁盘上占用实际空间来存储空数据块。只有真实(非空)的数据块会按原样写入磁盘。
NTFS文件系统也支持稀疏文件,Windows也提供了一些API来处理稀疏文件。
首先是检查文件系统支持稀疏文件,通过GetVolumeInformation
函数,判断lpFileSystemFlags
参数返回的值是否包含FILE_SUPPORTS_SPARSE_FILES
即可。通过C#进行P/Invoke调用代码如下:
public static bool IsSupportSparseFile(string path)
{
var result = GetVolumeInformation(path, null, 0, out NullRef<DWORD>(), out NullRef<DWORD>(), out var fileSystemFlags, null, 0);
if (result)
{
return (fileSystemFlags & FileSystemFlags.FILE_SUPPORTS_SPARSE_FILES) != 0;
}
else
{
throw new Win32Exception();
}
}
接下来是将文件设置为稀疏文件,需要用到DeviceIoControl
这一函数,然后配合FSCTL_SET_SPARSE
。通过C#进行P/Invoke调用代码如下:
public static bool SetAsSparseFile(FileStream file, bool isSparseFile)
{
#if NET40 || NET45
var size = Marshal.SizeOf(typeof(FILE_SET_SPARSE_BUFFER));
#else
var size = Marshal.SizeOf<FILE_SET_SPARSE_BUFFER>();
#endif
var FILE_SET_SPARSE_BUFFER = new FILE_SET_SPARSE_BUFFER
{
SetSparse = isSparseFile
};
var result = DeviceIoControl(file.SafeFileHandle.DangerousGetHandle(), FSCTL_SET_SPARSE, AsPointer(ref FILE_SET_SPARSE_BUFFER), size, NULL, 0, out _, NullRef<OVERLAPPED>());
return result;
}
如果直接向文件写入0,文件不会保持稀疏性。需要用DeviceIoControl
配合FSCTL_SET_ZERO_DATA
才行。如果使用SetEndOfFile
修改文件长度,文件会保持稀疏性。
更多关于稀疏文件的功能可以查看微软的文档。
有趣