how to create a sparse file in NTFS on windows using Python?

52 Views Asked by At

I want to create a sparse file on my computer, which work with windows 10 and a SSD(solid state disk) formatted to NTFS. I tried the followig code, generated by ChatGPT:

import ctypes

# Define constants for Windows API
FILE_ATTRIBUTE_NORMAL = 0x80
FILE_ATTRIBUTE_SPARSE_FILE = 0x200
FILE_FLAG_DELETE_ON_CLOSE = 0x04000000


def create_sparse_file(file_name, desired_file_size):
    handle = ctypes.windll.kernel32.CreateFileW(
        file_name,
        0x10000000,  # GENERIC_WRITE
        0,
        None,
        2,  # CREATE_ALWAYS
        FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_SPARSE_FILE,
        None,
    )

    if handle == -1:
        print("Error creating the file")
    else:
        # Set the file size to 1GB (size of the sparse file)
        ctypes.windll.kernel32.SetFilePointer(handle, desired_file_size, None, 0)
        ctypes.windll.kernel32.SetEndOfFile(handle)

        # Close the file
        ctypes.windll.kernel32.CloseHandle(handle)

        # Verify if the file is sparse
        result = ctypes.windll.kernel32.DeviceIoControl(
            handle,
            0x000900C4,  # FSCTL_QUERY_ALLOCATED_RANGES
            None,
            0,
            None,
            0,
            ctypes.byref(ctypes.c_uint64()),
            None,
        )

        if result == 0:
            print(f"File '{file_name}' is a sparse file.")
        else:
            print(f"Failed to create sparse file '{file_name}'")


if __name__ == '__main__':
    file_name = r'G:\test.iso'

    # Specify the desired file size (in bytes)
    desired_file_size = 1024 * 1024 * 1024  # 1 GB

    create_sparse_file(file_name, desired_file_size)

The target size is assigned as 1 GB. Atfer running the above code, it does generate a file with 1 GB size, but both 'Size' and 'Size on disk' attrbutes of the created file are 1GB, which indicading that the file actually is not sparse. How can I get a really sparse file?

1

There are 1 best solutions below

0
Roger Lipscombe On

the application must explicitly declare a file as sparse, using the FSCTL_SET_SPARSE control code.

-- https://learn.microsoft.com/en-us/windows/win32/fileio/sparse-file-operations

You cannot create a sparse file by calling CreateFile with FILE_ATTRIBUTE_SPARSE_FILE in the dwFlagsAndAttributes parameter. You must use the FSCTL_SET_SPARSE control code.

-- https://learn.microsoft.com/en-us/windows/win32/api/winioctl/ni-winioctl-fsctl_set_sparse