SetFileValidData在做什么? 与SetEndOfFile有什么不同?

我寻找一种asynchronous高效地扩展文件的方法。

在支持文档中, asynchronous磁盘I / O在Windows NT,Windows 2000和Windows XP上显示为Synchronous :

注:应用程序可以通过使用SetFileValidData函数更改文件的有效数据长度,然后发出一个WriteFile使前面提到的写入操作asynchronous。

在MSDN中, SetFileValidData是用于Sets the valid data length of the specified file函数。

但是我仍然不明白什么是“有效数据”,它和文件大小有什么区别?

我可以使用SetFilePointerExSetEndOfFile扩展文件大小,但是如何通过SetFileValidData做到这一点?

SetFileValidData不能input大于文件大小的参数。 在这种情况下, SetFileValidData的生命意义是什么?

Solutions Collecting From Web of "SetFileValidData在做什么? 与SetEndOfFile有什么不同?"

当使用SetEndOfFile增加文件的长度时,逻辑文件的长度会发生变化,并且会分配必要的磁盘空间,但实际上并没有将数据物理地写入与文件的新部分对应的磁盘扇区。 有效数据长度保持不变。

这意味着你可以使用SetEndOfFile非常快速地创建一个非常大的文件,如果你从文件的新部分读取,你只会得到零。 将实际数据写入文件的新部分时,有效数据长度会增加。

如果你只是想保留空间,那就好了,然后将数据顺序写入文件。 但是,如果你使文件非常大,并立即写入数据的末尾,零需要被写入文件的新的一部分,这将需要很长的时间。 如果实际上不需要文件包含零,则可以使用SetFileValidData跳过此步骤; 该文件的新部分将包含来自先前删除的文件的随机数据。

请注意,setendoffile不会将任何零写入磁盘上的任何分配扇区,只是在MFT记录内分配空间指针,然后更新整个文件系统的空间位图。 但是操作系统(或者FS)会在MFT记录中记录有效/逻辑文件的长度,如果从1GB扩大到2GB,那么所有的1GB应该全部为零,但是FS不会把零写到磁盘上,参考这个文件的有效长度知道1GB应该是零,如果你试图读取这个扩大的1GB的部分,它会直接在RAM中填充zeors,然后反馈给你的应用程序。 但是,如果你写访问这个1GB部分内的任何字节,FS必须从原来的1GB偏移量填充零到应用程序试图写入的当前指针,而不是从当前位置到尾部的其他字节文件,同时记录有效/逻辑长度从0到当前位置,物理大小和分配的大小仍然是2GB。 但是如果你使用setfilevaliddata,FS会直接将有效长度设置为2GB,并且不会填满任何零,不管你写的是什么位置,它只是写,但是无论你读的是什么位置,你都可以读出一些垃圾数据由其他应用程序生成。

同意Harry Johnston的回答,并且从实践的角度来看,虽然SetFileValidData具有性能优势,因为它不需要写入零,但它具有安全隐患,因为该文件可能包含来自其他已删除文件的数据。 所以需要一个特殊的权限,SE_MANAGE_VOLUME_NAME,正如MSDN提到的: http : //msdn.microsoft.com/en-us/library/windows/desktop/aa365544 (v=vs.85) .aspx

原因是,如果正在运行的程序的用户帐户没有这个权限,使用SetFileValidData可以将其他用户的已删除数据公开到该特定文件的视图中,所以普通用户(非管理员)不允许这样做。 即使对于特权用户,他们仍然需要注意在文件系统中使用ACL(访问控制列表)来保护该文件,使其不与非特权用户共享。

看来SenEndofFile并没有真正为目标文件分配保留的磁盘空间, SetFileValidData负责这个工作。

提到MSDN ,

您可以使用SetFileValidData函数在非常特定的情况下创建大文件,以便后续文件I / O的性能可以优于其他方法。 具体来说,如果文件的扩展部分很大,并且将随机写入,比如在数据库类型的应用程序中,则扩展和写入文件所需的时间将比使用SetEndOfFile和随机写入更快。

如果SetEndOfFile真的分配空间,那么随机写入时, SetFileValidData将不会比SetEndOfFile更好。 所以SetEndOfFile可能只是创建一个带有漏洞的稀疏文件,而SetFileValidData做实际的分配。