开发者

Reserve disk space before writing a file for efficiency

I have noticed a huge performance hit in one of my projects when logging is enabled for the first time. But when the log file limit is reached and the program starts writing to the beginning of the file again, the logging speed is much faster (about 50% faster). It's normal to set the log file size to hundreds of MBs.

Most download managers allocate dummy file with the required size before starting to download the file. This makes the writing more effecient because the whole chun开发者_Python百科k is allocated at once.

What is the best way to reserve disk space efficiently, by some fixed size, when my program starts for the first time?


void ReserveSpace(LONG spaceLow, LONG spaceHigh, HANDLE hFile)
{
    DWORD err = ::SetFilePointer(hFile, spaceLow, &spaceHigh, FILE_BEGIN);

    if (err == INVALID_SET_FILE_POINTER) {
        err = GetLastError();
        // handle error
    }
    if (!::SetEndOfFile(hFile)) {
        err = GetLastError();
        // handle error
    }
    err = ::SetFilePointer(hFile, 0, 0, FILE_BEGIN); // reset
}


wRAR is correct. Open a new file using your favourite library, then seek to the penultimate byte and write a 0 there. That should allocate all the required disk space.


If you are using C++ 17, you should do it with std::filesystem::resize_file

Link

Changes the size of the regular file named by p as if by POSIX truncate: if the file size was previously larger than new_size, the remainder of the file is discarded. If the file was previously smaller than new_size, the file size is increased and the new area appears as if zero-filled.

#include <iostream>
#include <iomanip>
#include <fstream>
#include <filesystem>

namespace fs = std::filesystem;

int main()
{
    fs::path p = fs::current_path() / "example.bin"; 
    std::ofstream(p).put('a');
    fs::resize_file(p, 1024*1024*1024); // resize to 1 G
}


You can use the SetFileValidData function to extend the logical length of a file without having to write out all that data to disk. However, because it can allow to read disk data to which you may not otherwise have been privileged, it requires the SE_MANAGE_VOLUME_NAME privilege to use. Carefully read the Remarks section of the documentation.

Also implementation of SetFileValidData depend on fs driver. NTFS support it and FAT only since Win7.


If you're using C#, you can call SetLength on a FileStream to instantly set an initial size to the file.

e.g.

using (var fileStream = File.Open(@"file.txt", FileMode.Create, FileAccess.Write, FileShare.Read))
{
    fileStream.SetLength(1024 * 1024 * 1024); // Reserve 1 GB
}


Here's a simple function that will work for files of any size:

void SetFileSize(HANDLE hFile, LARGE_INTEGER size)
{
    SetFilePointer(hFile, size, NULL, FILE_BEGIN);
    SetEndOfFile(hFile);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜