获取当前文件长度/ FileInfo.Length缓存和陈旧信息

Bro*_*ass 17 .net c# file-io

我正在跟踪文件的文件夹及其文件长度,至少有一个文件仍在写入.

我必须不断更新每个文件长度的记录,我将其用于其他目的.

Update如果文件长度与上一次更新中确定的长度不同,则每15秒调用一次该方法并更新文件的属性.

update方法如下所示:

var directoryInfo = new DirectoryInfo(archiveFolder);
var archiveFiles = directoryInfo.GetFiles()
                                .OrderByDescending(f=>f.CreationTimeUtc); 
foreach (FileInfo fi in archiveFiles)
{
    //check if file existed in previous update already
    var origFileProps = cachedFiles.GetFileByName(fi.FullName);
    if (origFileProps != null && fi.Length == origFileProps.EndOffset)
    {
        //file length is unchanged
    }
    else
    {
        //Update the properties of this file
        //set EndOffset of the file to current file length
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道DirectoryInfo.GetFiles()预先填充许多FileInfo属性的事实包括Length- 只要更新之间没有缓存(缓存的信息不应超过15秒),这是可以的.

我假设每个DirectoryInfo.GetFiles()调用生成一个集合,FileInfos其中所有集合都填充了新信息,然后使用FindFirstFile/ FindNextFileWin32 API.但事实似乎并非如此.

很少,但最终肯定会遇到这样一种情况,即写入的文件的文件长度一次不会更新5,10或甚至20分钟(如果重要的话,在Windows 2008 Server x64上进行测试) .

当前的解决方法是调用fi.Refresh()以强制更新每个文件信息.这内部似乎委托GetFileAttributesExWin32 API调用来更新文件信息.

虽然手动强制刷新的成本是可以忍受的,但我宁愿理解为什么我首先得到过时的信息.何时FileInfo生成信息以及它与呼叫的关系如何 DirectoryInfo.GetFiles()?我没有完全掌握下面的文件I/O缓存层吗?

Bro*_*ass 15

Raymond Chen现在写了一篇关于这个问题的非常详细的博文:

为什么仍然正在写入的文件报告的文件大小不正确?

在NTFS中,文件系统元数据不是目录条目的属性,而是文件的属性,其中一些元数据作为调整复制到目录条目中以提高目录枚举性能.像功能用FindFirstFile报告目录项,并通过将脂肪用户习惯于获得"免费"的元数据,他们能避免目录列表比FAT慢.directory-enumeration函数报告上次更新的元数据,如果目录条目是陈旧的,则可能与实际元数据不对应.

本质上,它归结为业绩:从收集的目录信息DirectoryInfo.GetFiles()FindFirstFile/ FindNextFileWin32 API的下方被缓存性能方面的考虑,以保证在NTFS比FAT老获取目录信息更好的性能.准确的文件大小信息只能通过调用来获取Get­File­Size()上的文件直接(在.NET呼叫Refresh()FileInfo或者获取FileInfo或打开和关闭这使得更新的文件信息的文件流传播到的目录-从文件名直接)元数据缓存.后一种情况解释了为什么在写入过程关闭文件时立即更新文件大小.

这也解释了问题似乎没有出现在Windows 2003 Server中 - 当时刷新缓存时更频繁地复制文件信息 - 对于Windows 2008 Server来说情况不再如此:

至于频率,答案有点复杂.从Windows Vista开始(及其相应的Windows Server版本,我不知道,但我确定你可以查找,而"你"我的意思是"Yuhong Bao"),NTFS文件系统执行这种礼貌复制时关闭文件对象的最后一个句柄.NTFS的早期版本复制的数据,而每当高速缓存刷新,这意味着它发生每隔一段时间根据不可预知的日程安排文件被打开.此更改的结果是目录条目现在不太频繁地更新,因此最后更新的文件大小比现在更新.

阅读完整的文章是非常有用的,并建议!


Woj*_*teq 5

我想你应该使用FileSystemWatcher并订阅Changed事件.更改指定的文件系统项时会触发它.