C# .NET FileInfo.LastWriteTime & FileInfo.LastAccessTime 错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1448716/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
.NET FileInfo.LastWriteTime & FileInfo.LastAccessTime are wrong
提问by Mr. Flibble
When I call FileInfo(path).LastAccessTime
or FileInfo(path).LastWriteTime
on a file that is in the process of being written it returns the time that the file was created, not the last time it was written to (ie. now).
当我调用FileInfo(path).LastAccessTime
或FileInfo(path).LastWriteTime
正在写入的文件时,它返回文件的创建时间,而不是上次写入的时间(即现在)。
Is there a way to get this information?
有没有办法获得这些信息?
Edit: To all the responses so far. I hadn't tried Refresh()
but that does not do it either. I am returned the time that the file was started to be written to. The same goes for the static method, and creating a new instance of FileInfo
.
编辑:到目前为止所有的回复。我没有尝试过,Refresh()
但这也不起作用。我返回文件开始写入的时间。静态方法也是如此,并创建FileInfo
.
Codymanix might have the answer, but I'm not running Windows Server (using Windows 7), and I don't know where the setting is to test.
Codymanix 可能有答案,但我没有运行 Windows Server(使用 Windows 7),而且我不知道要测试的设置。
Edit 2:Nobody finds it interesting that this function doesn't seem to work?
编辑 2:没有人觉得这个功能似乎不起作用很有趣?
回答by Jon Skeet
Have you tried calling Refresh()
just before accessing the property (to avoid getting a cached value)? If that doesn't work, have you looked at what Explorer shows at the same time? If Explorer is showing the wrong information, then it's probably something you can't really address - it might be that the information is only updated when the file handle is closed, for example.
您是否尝试过Refresh()
在访问属性之前调用(以避免获取缓存值)?如果这不起作用,您是否同时查看了 Explorer 显示的内容?如果资源管理器显示错误的信息,那么这可能是您无法真正解决的问题 - 例如,信息可能仅在文件句柄关闭时更新。
回答by Tommy Carlier
The FileInfo
values are only loaded once and then cached. To get the current value, call Refresh()
before getting a property:
这些FileInfo
值只加载一次,然后缓存。要获取当前值,请Refresh()
在获取属性之前调用:
f.Refresh();
t = f.LastAccessTime;
Another way to get the current value is by using the static methods on the File
class:
获取当前值的另一种方法是使用File
类上的静态方法:
t = File.GetLastAccessTime(path);
回答by scottm
From MSDN:
来自 MSDN:
When first called, FileSystemInfo calls Refresh and returns the cached information on APIs to get attributes and so on. On subsequent calls, you must call Refresh to get the latest copy of the information.
首次调用时,FileSystemInfo 调用 Refresh 并返回 API 上的缓存信息以获取属性等。在后续调用中,您必须调用 Refresh 以获取最新的信息副本。
If you're application is the one doing the writing, I think you are going to have to "touch" the file by setting the LastWriteTime property your self between each buffer of data you write. Some psuedocode:
如果您的应用程序是进行写入的人,我认为您将不得不通过在您写入的每个数据缓冲区之间设置自己的 LastWriteTime 属性来“触摸”文件。一些伪代码:
while(bytesWritten < totalBytes)
{
bytesWritten += br.Write(buffer);
myFileInfo.LastWriteTime = DateTime.Now;
}
I'm not sure how severely this will affect write performance.
我不确定这会严重影响写入性能。
回答by codymanix
There is a setting in windows which is sometimes set especially on server systems so that modified and accessed times for files are not set for better performance.
Windows 中有一个设置,有时会特别设置在服务器系统上,因此不会设置文件的修改和访问时间以获得更好的性能。
回答by James Kovacs
Starting in Windows Vista, last access time is not updated by default. This is to improve file system performance. You can find details here:
从 Windows Vista 开始,默认情况下不会更新上次访问时间。这是为了提高文件系统性能。您可以在此处找到详细信息:
To reenable last access time on the computer, you can run the following command:
要在计算机上重新启用上次访问时间,您可以运行以下命令:
fsutil behavior set disablelastaccess 0
fsutil 行为设置 disablelastaccess 0
回答by SleepyBoBos
Tommy Carlier's answer got me thinking....
汤米卡利尔的回答让我思考......
A good way to visualise the differences is seperately running the two snippets (I just used LinqPAD) simliar to below while also running sysinternals Process Monitor.
可视化差异的一个好方法是分别运行与下面类似的两个片段(我只使用了 LinqPAD),同时还运行 sysinternals Process Monitor。
while(true)
File.GetLastAccessTime([file path here]);
and
和
FileInfo bob = new FileInfo(path);
while(true){
string accessed = bob.LastAccessTime.ToString();
}
If you look at Process Monitor while running the first snippet you will see repeated and constant access attempts to the file for the LinqPAD process. The second snippet will do an initial access of the file, for which you will see activity in process monitor, and then very little afterwards.
如果您在运行第一个代码段时查看 Process Monitor,您将看到 LinqPAD 进程对文件的重复和持续访问尝试。第二个代码段将执行文件的初始访问,您将在进程监视器中看到活动,然后很少。
However if you go and modify the file (I just opened the text file I was monitoring using FileInfo and added a character and saved) you will see a series of access attempts by the LinqPAD process to the file in process monitor.
但是,如果您去修改文件(我刚刚打开了我使用 FileInfo 监视的文本文件并添加了一个字符并保存),您将看到 LinqPAD 进程对进程监视器中的文件进行的一系列访问尝试。
This illustrates the non-cached and cached behaviour of the two different approachs respectively.
这分别说明了两种不同方法的非缓存和缓存行为。
Will the non-cached approach wear a hole in the hard drive?!
非缓存方式会不会在硬盘上穿破洞?!
EDIT
编辑
I went away feeling all clever over my testing and then used the caching behaviour of FileInfo in my windows service (basically to sit in a loop and say 'Has-file-changed-has-file-changed...' before doing processing)
我在测试中感觉很聪明,然后在我的 Windows 服务中使用 FileInfo 的缓存行为(基本上是坐在一个循环中并在进行处理之前说“Has-file-changed-has-file-changed...”)
While this approach worked on my dev box, it did not work in the production environment, ie the process just kept running regardless if the file had changed or not. I ended up changing my approach to checking and just used GetLastAccessTime as part of it. Don't know why it would behave differently on production server....but I am not too concerned at this point.
虽然这种方法适用于我的开发箱,但它在生产环境中不起作用,即无论文件是否更改,进程都将继续运行。我最终改变了我的检查方法,只是使用了 GetLastAccessTime 作为其中的一部分。不知道为什么它在生产服务器上的行为会有所不同......但我现在并不太担心。
回答by Alois Kraus
As James has pointed out LastAccessTime is not updated.
正如 James 指出的LastAccessTime 没有更新。
The LastWriteTime has also undergone a twist since Vista. When the process has the file still open and another process checks the LastWriteTime it will not see the new write timefor a long time -- until the process has closed the file.
自 Vista 以来,LastWriteTime 也经历了一些变化。当进程仍然打开文件并且另一个进程检查 LastWriteTime 时,它将在很长一段时间内看不到新的写入时间——直到进程关闭文件。
As a workaround you can open and close the file from your external process. After you have done that you can try to read the LastWriteTime again which is then the up to date value.
作为解决方法,您可以从外部进程打开和关闭文件。完成后,您可以尝试再次读取 LastWriteTime,这是最新值。
File System Tunneling:
文件系统隧道:
If an application implements something like a rolling logger which closes the file and then renames it to a different file name you will also run into issues since the creation time and file size of the "old" file is remembered by the OS although you did create a new file. This includes wrong reports of the file size even if you did recreate log.txt from scratch which is still 0 bytes in size. This feature is called OS File System Tunneling which is still present on Windows 8.1 . An example how to work around this issue check out RollingFlatFileTracelistener from Enterprise Library.
如果应用程序实现了诸如关闭文件的滚动记录器之类的功能,然后将其重命名为不同的文件名,您也会遇到问题,因为尽管您确实创建了“旧”文件,但操作系统仍会记住它的创建时间和文件大小一个新文件。这包括文件大小的错误报告,即使您确实从头开始重新创建了大小仍然为 0 字节的 log.txt。此功能称为 OS 文件系统隧道,它仍然存在于 Windows 8.1 中。有关如何解决此问题的示例,请查看Enterprise Library 中的 RollingFlatFileTracelistener。
You can see the effects of file system tunneling on your own machine from the cmd shell.
您可以从 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
The file system is a state machine. Keeping states correctly synchronized is hard if you care about performance and correctness.
文件系统是一个状态机。如果您关心性能和正确性,则很难保持状态正确同步。
This strange tunneling syndrome is obviously still used by application which do e.g. autosave a file and move it to a save location and then recreate the file again at the same location. For these applications it makes to sense to give the file a new creation date because it was only copied around. Some installers do also such tricks to move files temporarily to a different location and write the contents back later to get past some file exists check for some install hooks.
这种奇怪的隧道综合症显然仍然被应用程序使用,例如自动保存文件并将其移动到保存位置,然后在同一位置再次重新创建文件。对于这些应用程序,给文件一个新的创建日期是有意义的,因为它只是被复制了。一些安装程序也会使用这样的技巧来临时将文件移动到不同的位置,然后将内容写回以通过某些文件是否存在检查某些安装挂钩。