我正在向使用纯C函数(fopen
,fwrite
,fclose
)的现有代码库添加一些功能,以将数据写入文件。不幸的是我不能改变文件i / o的实际机制,但是我必须为文件预先分配空间以避免碎片(这会在读取过程中破坏我们的性能)。有没有更好的方法来实际写入零或随机数据到文件?当我打开文件时,我知道文件的最终大小。
我知道我可以在linux上使用fallocate,但我不知道windows的等价物是什么。
谢谢!
答案 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。您还可以使用SetFilePointerEx
和SetEndOfFile
来扩展文件,但这样做仍然需要将零写入磁盘(除非文件稀疏,但这样做会破坏保留磁盘空间的点)。有关详细信息,请参阅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?
<块引用>使用SetFileInformationByHandle
函数,传递函数代码
FileAllocationInfo
和 FILE_ALLOCATION_INFO
结构。 “注意
这将减少碎片,但因为每次写入仍然
更新文件大小仍然会有同步和元数据
每次追加造成的开销。”
设置文件分配信息的效果只持续 你保持文件句柄打开。当您关闭文件句柄时,所有 您未使用的预分配空间将被释放。