如何在Windows上为C / C ++预先分配文件空间?

时间:2011-11-01 17:27:50

标签: c++ c windows file

我正在向使用纯C函数(fopenfwritefclose)的现有代码库添加一些功能,以将数据写入文件。不幸的是我不能改变文件i / o的实际机制,但是我必须为文件预先分配空间以避免碎片(这会在读取过程中破坏我们的性能)。有没有更好的方法来实际写入零或随机数据到文件?当我打开文件时,我知道文件的最终大小。

我知道我可以在linux上使用fallocate,但我不知道windows的等价物是什么。

谢谢!

6 个答案:

答案 0 :(得分:17)

以编程方式,在Windows上,您必须使用Win32 API函数来执行此操作:

SetFilePointerEx() followed by SetEndOfFile()

您可以使用这些功能为文件预分配群集并避免碎片。这比预先将数据写入文件更有效。在执行fopen()之前执行此操作。

如果您想完全避免使用Win32 API,您也可以使用system()函数以非编程方式执行此操作,以发出以下命令:

fsutil file createnew filename filesize

答案 1 :(得分:6)

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

我建议改为写出0。您还可以使用SetFilePointerExSetEndOfFile来扩展文件,但这样做仍然需要将零写入磁盘(除非文件稀疏,但这样做会破坏保留磁盘空间的点)。有关详细信息,请参阅Why does my single-byte write take forever?

答案 2 :(得分:3)

示例代码,请注意它不一定更快,特别是对于像NTFS这样的智能文件系统。

if (  INVALID_HANDLE_VALUE != (handle=CreateFile(fileName,GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_FLAG_SEQUENTIAL_SCAN,NULL) )) {                                               
        // preallocate 2Gb disk file                
        LARGE_INTEGER size;
        size.QuadPart=2048 * 0x10000;
        ::SetFilePointerEx(handle,size,0,FILE_BEGIN);
        ::SetEndOfFile(handle);
        ::SetFilePointer(handle,0,0,FILE_BEGIN);
}

答案 3 :(得分:1)

您可以使用_chsize()功能。

答案 4 :(得分:0)

在Code Project上查看此示例。在最初创建文件时,设置文件大小看起来非常简单。

http://www.codeproject.com/Questions/172979/How-to-create-a-fixed-size-file.aspx

FILE *fp = fopen("C:\\myimage.jpg","ab");

fseek(fp,0,SEEK_END);
long size = ftell(fp);

char *buffer = (char*)calloc(500*1024-size,1);
fwrite(buffer,500*1024-size,1,fp);

fclose(fp);

答案 5 :(得分:0)

这篇文章可能对你有帮助。

以下来自 Raymond 的文章可能会有所帮助。

How can I preallocate disk space for a file without it being reported as readable?

<块引用>

使用Set­File­Information­By­Handle函数,传递函数代码 File­Allocation­InfoFILE_ALLOCATION_INFO 结构。 “注意 这将减少碎片,但因为每次写入仍然 更新文件大小仍然会有同步和元数据 每次追加造成的开销。”

设置文件分配信息的效果只持续 你保持文件句柄打开。当您关闭文件句柄时,所有 您未使用的预分配空间将被释放。