我正在跟踪文件的文件夹及其文件长度,至少有一个文件仍在写入.
我必须不断更新每个文件长度的记录,我将其用于其他目的.
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
/ FindNextFile
Win32 API.但事实似乎并非如此.
很少,但最终肯定会遇到这样一种情况,即写入的文件的文件长度一次不会更新5,10或甚至20分钟(如果重要的话,在Windows 2008 Server x64上进行测试) .
当前的解决方法是调用fi.Refresh()
以强制更新每个文件信息.这内部似乎委托GetFileAttributesEx
Win32 API调用来更新文件信息.
虽然手动强制刷新的成本是可以忍受的,但我宁愿理解为什么我首先得到过时的信息.何时FileInfo
生成信息以及它与呼叫的关系如何 DirectoryInfo.GetFiles()
?我没有完全掌握下面的文件I/O缓存层吗?
Bro*_*ass 15
Raymond Chen现在写了一篇关于这个问题的非常详细的博文:
在NTFS中,文件系统元数据不是目录条目的属性,而是文件的属性,其中一些元数据作为调整复制到目录条目中以提高目录枚举性能.像功能用FindFirstFile报告目录项,并通过将脂肪用户习惯于获得"免费"的元数据,他们能避免目录列表比FAT慢.directory-enumeration函数报告上次更新的元数据,如果目录条目是陈旧的,则可能与实际元数据不对应.
本质上,它归结为业绩:从收集的目录信息DirectoryInfo.GetFiles()
和FindFirstFile
/ FindNextFile
Win32 API的下方被缓存性能方面的考虑,以保证在NTFS比FAT老获取目录信息更好的性能.准确的文件大小信息只能通过调用来获取GetFileSize()
上的文件直接(在.NET呼叫Refresh()
上FileInfo
或者获取FileInfo
或打开和关闭这使得更新的文件信息的文件流传播到的目录-从文件名直接)元数据缓存.后一种情况解释了为什么在写入过程关闭文件时立即更新文件大小.
这也解释了问题似乎没有出现在Windows 2003 Server中 - 当时刷新缓存时更频繁地复制文件信息 - 对于Windows 2008 Server来说情况不再如此:
至于频率,答案有点复杂.从Windows Vista开始(及其相应的Windows Server版本,我不知道,但我确定你可以查找,而"你"我的意思是"Yuhong Bao"),NTFS文件系统执行这种礼貌复制时关闭文件对象的最后一个句柄.NTFS的早期版本复制的数据,而每当高速缓存刷新,这意味着它发生每隔一段时间根据不可预知的日程安排文件被打开.此更改的结果是目录条目现在不太频繁地更新,因此最后更新的文件大小比现在更新.
阅读完整的文章是非常有用的,并建议!