windows .NET FileInfo.LastWriteTime和FileInfo.LastAccessTime错误

pxy2qtax  于 2023-06-30  发布在  Windows
关注(0)|答案(7)|浏览(178)

当我在一个正在被写入的文件上调用FileInfo(path).LastAccessTimeFileInfo(path).LastWriteTime时,它返回的是文件创建的时间,而不是文件最后一次被写入的时间(例如,文件被写入的时间)。现在)。
有没有办法得到这些信息?

***********我没有试过Refresh(),但它也没有。返回文件开始写入的时间。静态方法也是如此,创建一个新的FileInfo示例。

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

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

rn0zuynd

rn0zuynd1#

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

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

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

t = File.GetLastAccessTime(path);
nbnkbykc

nbnkbykc2#

从Windows Vista开始,默认情况下不会更新上次访问时间。这是为了提高文件系统性能。您可以在这里找到详细信息:
https://techcommunity.microsoft.com/t5/storage-at-microsoft/disabling-last-access-time-in-windows-vista-to-improve-ntfs/ba-p/423328
要在计算机上重新启用上次访问时间,可以运行以下命令:
fsutil行为设置disablelastaccess 0

wkftcu5l

wkftcu5l3#

正如James所指出的LastAccessTime没有更新
自Vista以来,LastWriteTime也经历了一个转折。当进程仍然打开文件并且另一个进程检查LastWriteTime时,它将在很长一段时间内看不到新的写入时间-直到进程关闭文件。
作为解决方法,您可以从外部进程打开和关闭该文件。完成后,您可以尝试再次读取LastWriteTime,这是最新的值。

文件系统隧道:

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

文件系统是一个状态机。如果您关心性能和正确性,那么保持状态正确同步是很困难的。
这种奇怪的隧道综合征显然仍然被这样的应用程序使用,例如。自动保存文件并将其移动到保存位置,然后在同一位置重新创建该文件。对于这些应用程序,为文件提供一个新的创建日期是有意义的,因为它只是被复制了。一些安装程序也会使用这样的技巧,将文件临时移动到不同的位置,然后在稍后写回内容,以通过一些文件存在检查来检查一些安装钩子。

um6iljoc

um6iljoc4#

你有没有试过在访问属性之前调用Refresh()(以避免获取缓存值)?如果这不起作用,你有没有看过资源管理器同时显示的内容?如果资源管理器显示错误的信息,那么它可能是你不能真正解决的问题-例如,可能只有在文件句柄关闭时才更新信息。

nsc4cvqm

nsc4cvqm5#

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

8i9zcol2

8i9zcol26#

从MSDN:
第一次调用时,FileSystemInfo调用Refresh并返回API上的缓存信息以获取属性等。在后续调用中,必须调用Refresh以获取信息的最新副本。
FileSystemInfo.Refresh()
如果你的应用程序是一个做写,我认为你将不得不“接触”的文件设置LastWriteTime属性之间的每个缓冲区的数据写你自己。一些伪代码:

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

我不确定这会严重影响写性能。

mctunoxg

mctunoxg7#

Tommy Carlier的回答让我思考……
一个可视化差异的好方法是分别运行下面的两个片段(我刚刚使用了LinqPAD),同时运行sysinternals进程监视器。

while(true)
    File.GetLastAccessTime([file path here]);

FileInfo bob = new FileInfo(path);

while(true){
    string accessed = bob.LastAccessTime.ToString();
}

如果在运行第一个代码段时查看ProcessMonitor,您将看到LinqPAD进程对文件的重复和持续的访问尝试。第二个代码片段将执行文件的初始访问,您将在进程监视器中看到活动,之后很少看到活动。
但是,如果你去修改文件(我刚刚打开了我正在使用FileInfo监视的文本文件,并添加了一个字符并保存了),你会看到LinqPAD进程对进程监视器中的文件的一系列访问尝试。
这分别说明了两种不同方法的非缓存和缓存行为。
非缓存方法是否会在硬盘驱动器上磨损一个洞?!

编辑

我离开的时候感觉自己在测试中很聪明,然后在我的Windows服务中使用了FileInfo的缓存行为(基本上是坐在一个循环中,在进行处理之前说'Has-file-changed-has-file-changed...')
虽然这种方法在我的开发盒上工作,但它在生产环境中不起作用,即无论文件是否更改,进程都将继续运行。我最终改变了我的检查方法,只是使用GetLastAccessTime作为它的一部分。不知道为什么在生产服务器上会有不同的表现……但我在这一点上并不太担心。

相关问题