I did write the code, here it is for scenario 1
The console output is :
Writing 65536 1 at offset 0
Flush
New file size : 65536 (virtual) 65536 (compressed)
New file size : 65536 (virtual) 65536 (compressed)
Writing 65536 sparse 0 at offset 65536
Flush
New file size : 131072 (virtual) 65536 (compressed)
New file size : 131072 (virtual) 65536 (compressed)
Writing 65536 1 at offset 131072
Flush
New file size : 196608 (virtual) 196608 (compressed)
New file size : 196608 (virtual) 196608 (compressed)
typedef enum {ONE, ZERO, ZERO_SPARSE} data_t;
const wchar_t* filePath = L"E:\\temp\\sparse.tmp";
LARGE_INTEGER EXGetFileSize(HANDLE f)
{
LARGE_INTEGER result = {0};
if (f != nullptr)
GetFileSizeEx(f, &result);
return result;
}
//end EXGetFileSize()
void logFileSize(HANDLE f)
{
LARGE_INTEGER vsize = EXGetFileSize(f);
LARGE_INTEGER fsize = {0};
DWORD highPart = 0;
fsize.LowPart = GetCompressedFileSize(filePath, &highPart);
fsize.HighPart = highPart;
std::cout << "New file size : " << vsize.QuadPart << (!f ? "?" : "") << " (virtual)" << "\t" << fsize.QuadPart << " (compressed)" << std::endl;
}
//end logFileSize()
void flushFile(HANDLE f)
{
FlushFileBuffers(f);
std::cout << "Flush" << std::endl;
logFileSize(f);
}
//end flushFile()
void writePacket(HANDLE f, size_t offset, data_t dataType, size_t size, bool byteByByte, bool flush)
{
std::cout << "Writing " << size << " " << ((dataType == ZERO_SPARSE) ? "sparse 0" : (dataType == ZERO) ? "real 0" : "1") << " at offset " << offset << std::endl;
const bool isSparse = (dataType == ZERO_SPARSE);
std::vector<unsigned char> v(size);
std::fill(v.begin(), v.end(), (dataType == ONE) ? 1 : 0);
LARGE_INTEGER _offset = {0};
_offset.QuadPart = offset;
BOOL b1 = SetFilePointerEx(f, _offset, nullptr, FILE_BEGIN);
BOOL b2 = FALSE;
DWORD numberOfBytesWritten = 0;
if (!byteByByte)
{
if (isSparse)
{
FILE_ZERO_DATA_INFORMATION fzdi = {0};
fzdi.FileOffset.QuadPart = offset;
fzdi.BeyondFinalZero.QuadPart = offset + size;
if (fzdi.BeyondFinalZero.QuadPart > EXGetFileSize(f).QuadPart)
{
BOOL b2 = SetFilePointerEx(f, fzdi.BeyondFinalZero, nullptr, FILE_BEGIN);
BOOL b4 = SetEndOfFile(f);
}
b2 = DeviceIoControl(f, FSCTL_SET_ZERO_DATA, &fzdi, sizeof(fzdi), nullptr, 0, &numberOfBytesWritten, nullptr);
}//end if (isSparse)
else
b2 = WriteFile(f, v.data(), v.size(), &numberOfBytesWritten, nullptr);
}
else//if (byteByByte)
{
for(size_t i = 0 ; i<v.size() ; ++i)
{
if (isSparse)
{
FILE_ZERO_DATA_INFORMATION fzdi = {0};
fzdi.FileOffset.QuadPart = offset+i;
fzdi.BeyondFinalZero.QuadPart = offset+i+1;
b2 = DeviceIoControl(f, FSCTL_SET_ZERO_DATA, &fzdi, sizeof(fzdi), nullptr, 0, &numberOfBytesWritten, nullptr);
}
else
b2 = WriteFile(f, v.data()+i, 1, &numberOfBytesWritten, nullptr);
if (flush)
FlushFileBuffers(f);
}
}//end if (byteByByte)
if (flush)
flushFile(f);
logFileSize(f);
}
//end writePacket()
int main()
{
HANDLE f = CreateFile(filePath, GENERIC_READ|GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0*FILE_FLAG_DELETE_ON_CLOSE, nullptr);
DWORD bytesReturned = 0;
BOOL b = DeviceIoControl(f, FSCTL_SET_SPARSE, nullptr, 0, nullptr, 0, &bytesReturned, nullptr);
const size_t ps = 64*1024;
size_t pi = 0;
writePacket(f, (pi++)*ps, data_t::ONE, ps, false, true);
writePacket(f, (pi++)*ps, data_t::ZERO_SPARSE, ps, false, true);
writePacket(f, (pi++)*ps, data_t::ONE, ps, false, true);
CloseHandle(f);
logFileSize(nullptr);
return 0;
}