如何在 Windows 上的 C/C++ 中为文件预分配空间?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7970333/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you pre-allocate space for a file in C/C++ on Windows?
提问by user1024191
I'm adding some functionality to an existing code base that uses pure C functions (fopen
, fwrite
, fclose
) to write data out to a file. Unfortunately I can't change the actual mechanism of file i/o, but I have to pre-allocate space for the file to avoid fragmentation (which is killing our performance during reads). Is there a better way to do this than to actually write zeros or random data to the file? I know the ultimate size of the file when I'm opening it.
我正在向使用纯 C 函数(fopen
, fwrite
, fclose
)将数据写入文件的现有代码库添加一些功能。不幸的是,我无法更改文件 i/o 的实际机制,但我必须为文件预先分配空间以避免碎片化(这会在读取过程中扼杀我们的性能)。有没有比实际将零或随机数据写入文件更好的方法呢?当我打开文件时,我知道文件的最终大小。
I know I can use fallocate on linux, but I don't know what the windows equivalent is.
我知道我可以在 linux 上使用 fallocate,但我不知道 windows 等价物是什么。
Thanks!
谢谢!
回答by Michael Goldshteyn
Programatically, on Windows you have to use Win32 API functions to do this:
以编程方式,在 Windows 上,您必须使用 Win32 API 函数来执行此操作:
SetFilePointerEx() followed by SetEndOfFile()
You can use these functions to pre-allocate the clusters for the file and avoid fragmentation. This works much more efficiently than pre-writing data to the file. Do this prior to doing your fopen()
.
您可以使用这些函数为文件预先分配集群并避免碎片化。这比将数据预写入文件更有效。在执行您的fopen()
.
If you want to avoid the Win32 API altogether, you can also do it non-programatically using the system() function to issue the following command:
如果您想完全避免 Win32 API,您也可以使用 system() 函数以非编程方式发出以下命令:
fsutil file createnew filename filesize
回答by Adam Rosenfield
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 Remarkssection of the documentation.
您可以使用该SetFileValidData
函数来扩展文件的逻辑长度,而无需将所有数据写入磁盘。但是,因为它可以允许读取您可能没有特权的磁盘数据,所以它需要SE_MANAGE_VOLUME_NAME
特权才能使用。仔细阅读文档的备注部分。
I'd recommend instead just writing out the 0's. You can also use SetFilePointerEx
and SetEndOfFile
to extend the file, but doing so still requires writing out zeros to disk (unless the file is sparse, but that defeats the point of reserving disk space). See Why does my single-byte write take forever?for more info on that.
我建议改为只写出 0。您还可以使用SetFilePointerEx
和SetEndOfFile
扩展文件,但这样做仍然需要将零写入磁盘(除非文件稀疏,但这与保留磁盘空间的意义相去甚远)。请参阅为什么我的单字节写入需要永远?有关更多信息。
回答by Martin Beckett
Sample code, note that it isn't necessarily faster especially with smart filesystems like NTFS.
示例代码,请注意它不一定更快,尤其是对于像 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);
}
回答by Jim Fell
Check out this example on Code Project. It looks pretty straightforward to set the file size when the file is initially crated.
在 Code Project 上查看此示例。在最初创建文件时设置文件大小看起来非常简单。
http://www.codeproject.com/Questions/172979/How-to-create-a-fixed-size-file.aspx
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);