26

当我调用FileInfo(path).LastAccessTimeFileInfo(path).LastWriteTime处理正在写入的文件时,它会返回文件的创建时间,而不是上次写入的时间(即现在)。

有没有办法获取这些信息?

编辑:到目前为止的所有回复。我没有尝试过Refresh(),但这也没有。我返回文件开始写入的时间。静态方法也是如此,并创建FileInfo.

Codymanix 可能有答案,但我没有运行 Windows Server(使用 Windows 7),而且我不知道要在哪里测试设置。

编辑2:没有人觉得这个功能似乎不起作用很有趣?

4

7 回答 7

16

这些FileInfo值只加载一次,然后缓存。要获取当前值,请Refresh()在获取属性之前调用:

f.Refresh();
t = f.LastAccessTime;

获取当前值的另一种方法是使用File类上的静态方法:

t = File.GetLastAccessTime(path);
于 2009-09-19T15:08:42.787 回答
9

Starting in Windows Vista, last access time is not updated by default. This is to improve file system performance. You can find details here:

http://blogs.technet.com/b/filecab/archive/2006/11/07/disabling-last-access-time-in-windows-vista-to-improve-ntfs-performance.aspx

To reenable last access time on the computer, you can run the following command:

fsutil behavior set disablelastaccess 0

于 2010-12-07T20:29:32.637 回答
5

正如 James 指出的LastAccessTime 没有更新


自 Vista 以来,LastWriteTime 也发生了变化。当进程仍然打开文件并且另一个进程检查 LastWriteTime 时,它​​将很长时间看不到新的写入时间——直到进程关闭文件。

作为一种解决方法,您可以从外部进程打开和关闭文件。完成后,您可以尝试再次读取 LastWriteTime,这是最新的值。


文件系统隧道:

如果应用程序实现了类似滚动记录器的功能,它会关闭文件然后将其重命名为不同的文件名,那么您也会遇到问题,因为操作系统会记住“旧”文件的创建时间和文件大小,尽管您确实创建了一个新文件。这包括文件大小的错误报告,即使您确实从头开始重新创建 log.txt,其大小仍然为 0 字节。此功能称为 OS 文件系统隧道,它仍然存在于 Windows 8.1 中。如何解决此问题的示例请查看Enterprise Library 中的 RollingFlatFileTracelistener

您可以从 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

文件系统是一个状态机。如果您关心性能和正确性,则很难保持状态正确同步。

这种奇怪的隧道综合症显然仍然被应用程序使用,例如自动保存文件并将其移动到保存位置,然后在同一位置再次重新创建文件。对于这些应用程序,给文件一个新的创建日期是有意义的,因为它只是被复制的。一些安装程序也会使用这种技巧将文件临时移动到不同的位置并稍后将内容写回以通过某些文件存在检查某些安装挂钩。

于 2015-07-05T19:15:19.897 回答
4

Windows 中有一个设置,有时特别是在服务器系统上设置,因此不会设置文件的修改和访问时间以获得更好的性能。

于 2009-09-19T15:49:59.357 回答
4

您是否尝试过Refresh()在访问属性之前调用(以避免获取缓存值)?如果这不起作用,您是否查看过 Explorer 同时显示的内容?如果资源管理器显示错误信息,则可能是您无法真正解决的问题 - 例如,信息可能仅在文件句柄关闭时更新。

于 2009-09-19T15:07:43.460 回答
4

来自 MSDN:

首次调用时,FileSystemInfo 调用 Refresh 并返回 API 上的缓存信息以获取属性等。在随后的调用中,您必须调用 Refresh 以获取信息的最新副本。

FileSystemInfo.Refresh()

如果您的应用程序是进行写入的应用程序,我认为您将不得不通过在您写入的每个数据缓冲区之间设置您自己的 LastWriteTime 属性来“触摸”文件。一些伪代码:

while(bytesWritten < totalBytes)
{
   bytesWritten += br.Write(buffer);
   myFileInfo.LastWriteTime = DateTime.Now;
}

我不确定这会对写入性能产生多大的影响。

于 2009-09-19T15:08:51.727 回答
0

汤米卡利尔的回答让我思考......

可视化差异的一个好方法是分别运行类似于下面的两个片段(我只是使用 LinqPAD),同时还运行 sysinternals Process Monitor。

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 的缓存行为(基本上是坐在一个循环中并在处理之前说'Has-file-changed-has-file-changed...')

虽然这种方法适用于我的开发盒,但它在生产环境中不起作用,即无论文件是否更改,进程都会继续运行。我最终改变了我的检查方法,只是使用了 GetLastAccessTime 作为其中的一部分。不知道为什么它在生产服务器上的行为会有所不同......但我现在并不太担心。

于 2012-10-25T05:53:14.133 回答