当我在正在写入的文件上调用FileInfo(path).LastAccessTime
或FileInfo(path).LastWriteTime
时,将返回文件创build的时间,而不是最后一次写入的时间(即现在) 。
有没有办法获得这些信息?
编辑:到目前为止所有的回应。 我没有尝试Refresh()
但也没有做到这一点。 我回到了文件开始写入的时间。 这同样适用于静态方法,并创buildFileInfo
的新实例。
Codymanix可能有答案,但我没有运行Windows Server(使用Windows 7),我不知道设置要testing的位置。
编辑2:没有人觉得这个function似乎不工作有趣吗?
FileInfo
值只加载一次,然后缓存。 要获取当前值,请在获取属性之前调用Refresh()
:
f.Refresh(); t = f.LastAccessTime;
另一种获取当前值的方法是使用File
类的静态方法:
t = File.GetLastAccessTime(path);
在Windows中有一个设置,有时特别是在服务器系统上设置,所以修改和访问文件的时间没有被设置为更好的性能。
来自MSDN:
首次调用时,FileSystemInfo调用Refresh并返回缓存的API信息以获取属性等。 在后续的通话中,您必须致电刷新才能获取最新的信息。
FileSystemInfo.Refresh()
如果你的应用程序是写这个程序的话,我认为你将不得不通过在你写的每个数据缓冲区之间设置LastWriteTime属性来“触摸”这个文件。 一些伪码:
while(bytesWritten < totalBytes) { bytesWritten += br.Write(buffer); myFileInfo.LastWriteTime = DateTime.Now; }
我不确定这会严重影响写入性能。
从Windows Vista开始,上次访问时间默认情况下不会更新。 这是为了提高文件系统的性能。 你可以在这里找到细节:
要在计算机上重新启用上次访问时间,可以运行以下命令:
fsutil行为集合disablelastaccess 0
您是否在访问属性之前尝试调用Refresh()
(以避免获取缓存的值)? 如果这不起作用,你有没有看过资源管理器同时显示? 如果资源管理器显示错误信息,那么这可能是您无法真正解决的问题 – 例如,可能只是在关闭文件句柄时更新信息。
正如James指出的,LastAccessTime没有更新。
从Vista开始,LastWriteTime也经历了一个转折。 当进程已经打开文件时,另一个进程检查LastWriteTime,直到进程已经关闭文件,长时间不会看到新的写入时间。 作为一种解决方法,您可以从外部进程打开和关闭该文件。 完成之后,您可以尝试再次读取LastWriteTime,这是最新的值。
如果一个应用程序实现了类似滚动记录器关闭文件,然后重命名为不同的文件名,你也会遇到问题,因为“旧”文件的创建时间和文件大小是由操作系统记住,虽然你创建一个新的文件。 这包括文件大小的错误报告,即使您从零开始重新创建了log.txt,它仍然是0字节大小。 这个功能被称为OS文件系统隧道,它仍然存在于Windows 8.1上。 有关如何实现此问题的示例,请查看Enterprise Library中的RollingFlatFileTracelistener( http://home.elka.pw.edu.pl/~mrudnik/CREAM/Logging/Src/Logging/Tracelistners/RollingFlatFileTracelistner.cs )。
您可以从cmd shell中看到文件系统隧道对您自己的机器的影响。
echo test > file1.txt ren file1.txt file2.txt Wait one minute echo test > file1.txt dir /tc file*.txt ... 05.07.2015 19:26 7 file1.txt 05.07.2015 19:26 7 file2.txt
文件系统是一个状态机。 如果你关心性能和正确性,保持状态正确同步是很困难的。 这种奇怪的隧道综合征显然仍然被应用程序所使用,例如自动保存文件并将其移动到保存位置,然后在同一位置重新创建文件。 对于这些应用程序来说,它使文件有一个新的创建日期,因为它只是被复制。 有些安装程序也会将文件临时移动到不同的位置,并稍后将内容写回来,以便通过某些文件存在检查某些安装挂钩。
汤米·卡莱尔的回答让我想到了….
一个很好的方式来形象化差异是单独运行两个片段(我刚刚使用LinqPAD)同时运行sysinternals进程监视器。
while(true) File.GetLastAccessTime([file path here]);
和
FileInfo bob = new FileInfo(path); while(true){ string accessed = bob.LastAccessTime.ToString(); }
如果您在运行第一个代码片段时查看Process Monitor,则会看到对LinqPAD进程的文件进行重复和持续的访问尝试。 第二个片段会对文件进行初始访问,您将在进程监视器中看到活动,然后很少。
但是,如果你去修改文件(我刚刚打开了我使用FileInfo监视的文本文件,并添加了一个字符并保存),你将看到LinqPAD进程对进程监视器中文件的一系列访问尝试。
这分别说明了两种不同方法的非缓存和缓存行为。
非缓存的方法是否会在硬盘上出现漏洞?
编辑
我走了,感觉我的测试都很聪明,然后使用我的Windows服务中的FileInfo的缓存行为(基本上是坐在一个循环,并说'已文件更改已文件更改…'在进行处理之前)
虽然这种方法在我的开发箱上工作,但它在生产环境中无法正常工作,即无论文件是否更改,过程都保持运行。 我最终改变了我的方法来检查,并使用GetLastAccessTime作为它的一部分。 不知道为什么它会在生产服务器上表现不一样……但是我并不太在意这一点。