如何获取 windows 上稀疏文件的真实磁盘使用情况?

How to get the true disk usage of a sparse file on windows?

我正在看一本名为“windows via c/c++”的书。 它说程序员可以在 FileMapping.

上创建一个带有 VirtualAlloc() 的稀疏文件

而且我在书中的文件属性中看到这个稀疏文件占用了 1MB。
书上说它实际上只需要 64KB 的磁盘空间。

那么如何获取稀疏文件的实际大小呢? 此外,我创建了一个备用文件,代码如下:

#include <iostream>
#include <Windows.h>
int main()
{
    using namespace std;
    HANDLE fileHandle = CreateFile(TEXT("D:\sfile.txt"), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
    if(fileHandle==INVALID_HANDLE_VALUE)
    {
        cout << "INVALID FILE HANDLE" << endl;
        return 1;
    }
    HANDLE hFileMapping = CreateFileMapping(fileHandle, nullptr, PAGE_READWRITE|SEC_RESERVE, 0, 4*1024 * 1024, nullptr);
    if(hFileMapping==INVALID_HANDLE_VALUE||hFileMapping==NULL)
    {
        cout << "INVALID FILE MAPPING HANDLE" << endl;
        return 1;
    }
    PVOID view = MapViewOfFile(hFileMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 1024 * 1024);
    if(view == nullptr)
    {
        cout << "map failed" << endl;
        return 1;
    }
    PVOID revisePos = static_cast<PLONG_PTR>(view) + 512;
    auto allocatePos =  (char*)VirtualAlloc(revisePos, 1024 * 1024, MEM_COMMIT, PAGE_READWRITE);
    char mess[] = "123456789 hello world!";
    strcpy_s(static_cast<char*>(revisePos), sizeof(mess), mess);
    UnmapViewOfFile(view);
    CloseHandle(hFileMapping);
    CloseHandle(fileHandle);

}

它将创建 4MB 的文件,尽管我只是尝试 VirtualAlloc 1MB。通过查看文件的属性,似乎这个文件实际上在 windows 上占用了 4MB。

为什么 window 不会压缩稀疏文件?如果windows不会压缩,我什么时候需要一个稀疏文件。

你应该检查documentation而不是依赖这本书。

您使用 PAGE_READWRITE|SEC_RESERVE 个选项创建了一个由普通文件支持的文件映射。

文件大小应该增加 4 MB 以匹配映射对象的大小:

If an application specifies a size for the file mapping object that is larger than the size of the actual named file on disk and if the page protection allows write access (that is, the flProtect parameter specifies PAGE_READWRITE or PAGE_EXECUTE_READWRITE), then the file on disk is increased to match the specified size of the file mapping object.

SEC_RESERVE完全没有效果:

This attribute has no effect for file mapping objects that are backed by executable image files or data files (the hfile parameter is a handle to a file).