【问题标题】:Reserve disk space before writing a file for efficiency在写入文件之前保留磁盘空间以提高效率
【发布时间】:2010-03-01 15:15:13
【问题描述】:

我注意到第一次启用日志记录时,我的一个项目的性能受到了巨大影响。但是当达到日志文件限制并且程序再次开始写入文件开头时,日志记录速度要快得多(大约快 50%)。将日志文件大小设置为数百 MB 是正常的。

大多数下载管理器在开始下载文件之前会分配所需大小的虚拟文件。这使得写入更有效,因为整个块是一次分配的。

当我的程序第一次启动时,以某个固定大小有效地保留磁盘空间的最佳方法是什么?

【问题讨论】:

  • 你为什么不能用你想要的任何大小创建一个空日志?
  • 这正是我所需要的。我的问题是如何做到这一点。在磁盘上创建具有一定大小的空日志文件的最有效方法是什么?
  • 这是一个 Windows 问题,而不是 C++ 问题。这是 Windows API 的问题,而不是如何使用 C++ 程序调用它。我建议删除 C++ 标签;这里有很多 .NET 类型,他们知道要寻找什么。

标签: windows


【解决方案1】:
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
}

【讨论】:

  • 谢谢。这正是我想要的。
【解决方案2】:

wRAR 是正确的。 使用您喜欢的库打开一个新文件,然后查找倒数第二个字节并在其中写入 0。这应该分配所有需要的磁盘空间。

【讨论】:

  • 是真的吗?我一直认为 NTFS 支持文件漏洞,但我现在找不到它的来源。
  • "大多数应用程序不知道稀疏文件并且不会创建稀疏文件。应用程序正在读取稀疏文件的事实对应用程序是透明的。知道稀疏文件的应用程序应该确定其数据集是否适合保存在稀疏文件中。确定后,应用程序必须使用 FSCTL_SET_SPARSE 控制代码将文件显式声明为稀疏文件。"
  • 正如 wRAR 所暗示的,NTFS 支持文件漏洞,但您必须使用 FSCTL_SET_SPARSE 或通过设置要压缩的文件来显式创建。
  • 如果磁盘被压缩,那么所有文件本质上都是自动“稀疏”的。孔将被压缩,就像稀疏文件所获得的一样多。因此,在这种情况下,您需要用“虚拟”数据填充日志文件,这些数据可压缩与实际日志数据的数量相同。也许通过克隆实际日志数据的前 4096 个字节?
【解决方案3】:

如果您使用的是 C++ 17,则应使用 std::filesystem::resize_file

Link

改变由 p 命名的常规文件的大小,就像通过 POSIX 截断一样:如果文件大小以前大于 new_size,则丢弃文件的其余部分。如果文件之前小于 new_size,则文件大小会增加,新区域会显示为零填充。

#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
}

【讨论】:

  • 我喜欢这种方法。我建议的唯一区别是打开和关闭文件而不实际写入任何内容,例如:fstream fs; fs.open(路径, ios::binary | ios::out); fs.close();
【解决方案4】:

您可以使用SetFileValidData 函数来扩展文件的逻辑长度,而无需将所有数据写入磁盘。但是,因为它可以允许读取您可能没有特权的磁盘数据,所以它需要SE_MANAGE_VOLUME_NAME 特权才能使用。仔细阅读文档的备注部分。

SetFileValidData 的实现也依赖于 fs 驱动程序。 NTFS 从 Win7 起才支持它和 FAT。

【讨论】:

    【解决方案5】:

    这是一个适用于任何大小文件的简单函数:

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

    【讨论】:

      【解决方案6】:

      如果您使用 C#,则可以在 FileStream 上调用 SetLength 以立即设置文件的初始大小。

      例如

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-06-06
        • 1970-01-01
        • 1970-01-01
        • 2021-10-24
        • 2017-09-24
        • 1970-01-01
        • 2013-10-05
        • 1970-01-01
        相关资源
        最近更新 更多