GetVolumeInformation:
Retrieves information about the file system and volume associated with the specified root directory.
GetVolumeInformation(
lpRootPathName: PChar; {磁盘驱动器代码字符串}
lpVolumeNameBuffer: PChar; {磁盘驱动器卷标名称}
nVolumeNameSize: DWORD; {磁盘驱动器卷标名称长度}
lpVolumeSerialNumber: PDWORD; {磁盘驱动器卷标序列号}
var lpMaximumComponentLength: DWORD; {系统允许的最大文件名长度}
var lpFileSystemFlags: DWORD; {文件系统标识}
lpFileSystemNameBuffer: PChar; {文件操作系统名称}
nFileSystemNameSize: DWORD {文件操作系统名称长度}
): BOOL;
GetFileInformationByHandle:
Retrieves file information for the specified file.
参数 类型及说明
hFile Long,文件的句柄
lpFileInformation BY_HANDLE_FILE_INFORMATION,用于容纳文件信息的结构参数 类型及说明
hFile Long,文件的句柄
lpFileInformation BY_HANDLE_FILE_INFORMATION,用于容纳文件信息的结构
GetCompressedFileSize:
Retrieves the actual number of bytes of disk storage used to store a specified file
SetFilePointer:
DWORD SetFilePointer( HANDLE hFile, // 文件句柄 LONG lDistanceToMove, // 偏移量(低位) PLONG lpDistanceToMoveHigh, // 偏移量(高位) DWORD dwMoveMethod // 基准位置FILE_BEGIN:文件开始位置 FILE_CURRENT:文件当前位置 FILE_END:文件结束位置 说明:移动一个打开文件的指针
DWORD SetFilePointer( HANDLE hFile, // 文件句柄 LONG lDistanceToMove, // 偏移量(低位) PLONG lpDistanceToMoveHigh, // 偏移量(高位) DWORD dwMoveMethod // 基准位置FILE_BEGIN:文件开始位置 FILE_CURRENT:文件当前位置 FILE_END:文件结束位置 说明:移动一个打开文件的指针
SetEndOfFile:
设置文件的结束位置
VolumeSupportsSparseFiles(LPCTSTR lpRootPathName ){
DWORD dwVolFlags ;
GetVolumeInformation(lpRootPathName, NULL, MAX_PATH, NULL, NULL , &dwVolFlags, NULL, MAX_PATH );
return (dwVolFlags & FILE_SUPPORTS_SPARSE_FILES) ? TRUE : FALSE ;
}
BOOl IsSparseFile(LPCTSTR lpFileName ){
HANDLE hFile = CreateFile(lpFileName, GENERIC_READ, 0, NULL , OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if (hFile == INVALID_HANDLE_VALUE )
return FALSE ;
BY_HANDLE_FILE_INFORMATION bhfi ;
GetFileInformationByHandle(hFile, &bhfi );
CloseHandle(hFile );
return (bhfi.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) ? TRUE : FALSE ;}
BOOL GetSparseFileSize(LPCTSTR lpFileName ){
HANDLE hFile = CreateFile(lpFileName, GENERIC_READ, 0, NULL , OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if (hFile == INVALID_HANDLE_VALUE )
return FALSE ;
LARGE_INTEGER liSparseFileSize ;
GetFileSizeEx(hFile, &liSparseFileSize );
LARGE_INTEGER liSparseFileCompressedSize ;
liSparseFileCompressedSize.LowPart = GetCompressedFileSize(lpFileName , (LPDWORD)&liSparseFileCompressedSize.HighPart
);
wprintf(L"\nFile total size: %I64uKB\nActual size on disk: %I64uKB\n" , liSparseFileSize.QuadPart
/ 1024,
liSparseFileCompressedSize.QuadPart
/ 1024);
CloseHandle(hFile
);
return TRUE ;}
HANDLE CreateSparseFile(LPCTSTR lpFileName )
{HANDLE hSparseFile = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL , CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if (hSparseFile == INVALID_HANDLE_VALUE )
return hSparseFile; DWORD dwTemp;
DeviceIoControl(hSparseFile, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &dwTemp, NULL
);
return hSparseFile ;
}
void SetSparseRange(HANDLE hSparseFile, LONGLONG start, LONGLONG size )
{FILE_ZERO_DATA_INFORMATION fzdi ;fzdi.FileOffset.QuadPart = start;
fzdi.BeyondFinalZero.QuadPart = start + size ;
// Mark the range as sparse zero block
DWORD dwTemp ;
DeviceIoControl(hSparseFile, FSCTL_SET_ZERO_DATA, &fzdi, sizeof(fzdi ), NULL, 0, &dwTemp, NULL );}
BOOL GetSparseRanges(LPCTSTR lpFileName )
{
// Open the file for read
HANDLE hFile = CreateFile(lpFileName, GENERIC_READ, 0, NULL , OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if (hFile == INVALID_HANDLE_VALUE )
return FALSE ;
LARGE_INTEGER liFileSize ;
GetFileSizeEx(hFile, &liFileSize );
// Range to be examined (the whole file)
FILE_ALLOCATED_RANGE_BUFFER queryRange ;queryRange.FileOffset.QuadPart = 0;
queryRange.Length = liFileSize ;
// Allocated areas info
FILE_ALLOCATED_RANGE_BUFFER allocRanges [1024];
DWORD nbytes ;
BOOL fFinished ;
_putws(L"\nAllocated ranges in the file:"
);
do
{fFinished = DeviceIoControl(hFile, FSCTL_QUERY_ALLOCATED_RANGES , &queryRange, sizeof(queryRange), allocRanges , sizeof(allocRanges), &nbytes, NULL );
if (!fFinished ){
)
{
wprintf(L"DeviceIoControl failed w/err 0x%08lx\n", dwError
);
CloseHandle(hFile
);
return FALSE ;}
}
// Calculate the number of records returned
DWORD dwAllocRangeCount = nbytes /
sizeof(FILE_ALLOCATED_RANGE_BUFFER );
// Print each allocated range
for (DWORD i = 0; i < dwAllocRangeCount; i ++)
{
wprintf(L"allocated range: [%I64u] [%I64u]\n" ,
allocRanges[i].FileOffset.QuadPart ,
allocRanges[i].Length.QuadPart
);
}
if (!fFinished && dwAllocRangeCount
> 0)
{
queryRange.FileOffset.QuadPart = allocRanges[dwAllocRangeCount - 1].FileOffset.QuadPart + allocRanges[dwAllocRangeCount - 1].Length.QuadPart ;
queryRange.Length.QuadPart = liFileSize.QuadPart -
queryRange.FileOffset.QuadPart ;}}
while (!fFinished );
CloseHandle(hFile );
return TRUE ;}
int
_tmain(int argc, _TCHAR* argv []){
if (!VolumeSupportsSparseFiles(L"C:\\" ))
{wprintf(L"Volume %s does not support sparse streams\n", L"C:\\" );
return 1;}
LPCWSTR lpFileName = L"SparseFile.tmp";
wprintf(L"Create sparse file: %s\n", lpFileName );
HANDLE hSparseFile = CreateSparseFile(lpFileName );
if (hSparseFile == INVALID_HANDLE_VALUE ){
wprintf(L"CreateFile failed w/err 0x%08lx\n", GetLastError ());
return 1;}
// Write a large block of data
const DWORD dwBlockLength = 512 * 1024;
BYTE* lpBlock = new BYTE[dwBlockLength ];
for (DWORD i = 0; i < dwBlockLength; i ++){lpBlock[i ] = 0xFF;}
DWORD dwBytesWritten ;
WriteFile(hSparseFile, lpBlock, dwBlockLength, &dwBytesWritten, NULL );
delete[] lpBlock ;
SetSparseRange(hSparseFile, 0, 64 * 1024 /*64KB*/ );
SetSparseRange(hSparseFile , 128 * 1024, 128 * 1024);
SetFilePointer(hSparseFile, 0x40000000 /*1GB*/, NULL, FILE_END);
SetEndOfFile(hSparseFile );
CloseHandle(hSparseFile );
BOOL fIsSparse = IsSparseFile(lpFileName );
wprintf(L"The file is%s sparse\n", fIsSparse ? L"" : L" not" );
GetSparseFileSize(lpFileName );
GetSparseRanges(lpFileName );
return 0;
}