我正在寻找一种方法来查看文件在C#中的最后修改时间。我拥有对该文件的完全访问权限。
我正在寻找一种方法来查看文件在C#中的最后修改时间。我拥有对该文件的完全访问权限。
Answers:
您只需要File.GetLastWriteTime
静态方法。
例:
var lastModified = System.IO.File.GetLastWriteTime("C:\foo.bar");
Console.WriteLine(lastModified.ToString("dd/MM/yy HH:mm:ss"));
但是请注意,在极少数情况下,写入文件时系统不会更新上次修改的时间(这可以作为高频写入的优化(例如日志记录或错误)而有意发生),则此方法将失败,您将需要从系统订阅文件写入通知,并不断进行监听。
请注意,函数File.GetLastWriteTime并不总是按预期运行,操作系统有时有时不会立即更新这些值。即使文件已经被修改过,您也可能会获得旧的时间戳记。
行为可能因OS版本而异。例如,此单元测试每次在我的开发人员机器上都能正常运行,但是在我们的构建服务器上始终会失败。
[TestMethod]
public void TestLastModifiedTimeStamps()
{
var tempFile = Path.GetTempFileName();
var lastModified = File.GetLastWriteTime(tempFile);
using (new FileStream(tempFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
}
Assert.AreNotEqual(lastModified, File.GetLastWriteTime(tempFile));
}
请参阅File.GetLastWriteTime似乎正在返回“过期”值
您的选择:
a)偶尔会有疏忽。
b)建立一个活动组件,以实现观察者模式(例如tcp服务器客户端结构),直接传达更改,而不是写入/读取文件。快速而灵活,但又有依赖性和可能的故障点(当然还有一些工作)。
c)通过替换其他进程定期读取的专用信号文件的内容来确保信令过程。它不像轮询过程那样聪明,并且比调用File.GetLastWriteTime要大得多的开销,但是如果不经常从太多地方检查内容,它将可以完成工作。
/// <summary>
/// type to set signals or check for them using a central file
/// </summary>
public class FileSignal
{
/// <summary>
/// path to the central file for signal control
/// </summary>
public string FilePath { get; private set; }
/// <summary>
/// numbers of retries when not able to retrieve (exclusive) file access
/// </summary>
public int MaxCollisions { get; private set; }
/// <summary>
/// timespan to wait until next try
/// </summary>
public TimeSpan SleepOnCollisionInterval { get; private set; }
/// <summary>
/// Timestamp of the last signal
/// </summary>
public DateTime LastSignal { get; private set; }
/// <summary>
/// constructor
/// </summary>
/// <param name="filePath">path to the central file for signal control</param>
/// <param name="maxCollisions">numbers of retries when not able to retrieve (exclusive) file access</param>
/// <param name="sleepOnCollisionInterval">timespan to wait until next try </param>
public FileSignal(string filePath, int maxCollisions, TimeSpan sleepOnCollisionInterval)
{
FilePath = filePath;
MaxCollisions = maxCollisions;
SleepOnCollisionInterval = sleepOnCollisionInterval;
LastSignal = GetSignalTimeStamp();
}
/// <summary>
/// constructor using a default value of 50 ms for sleepOnCollisionInterval
/// </summary>
/// <param name="filePath">path to the central file for signal control</param>
/// <param name="maxCollisions">numbers of retries when not able to retrieve (exclusive) file access</param>
public FileSignal(string filePath, int maxCollisions): this (filePath, maxCollisions, TimeSpan.FromMilliseconds(50))
{
}
/// <summary>
/// constructor using a default value of 50 ms for sleepOnCollisionInterval and a default value of 10 for maxCollisions
/// </summary>
/// <param name="filePath">path to the central file for signal control</param>
public FileSignal(string filePath) : this(filePath, 10)
{
}
private Stream GetFileStream(FileAccess fileAccess)
{
var i = 0;
while (true)
{
try
{
return new FileStream(FilePath, FileMode.Create, fileAccess, FileShare.None);
}
catch (Exception e)
{
i++;
if (i >= MaxCollisions)
{
throw e;
}
Thread.Sleep(SleepOnCollisionInterval);
};
};
}
private DateTime GetSignalTimeStamp()
{
if (!File.Exists(FilePath))
{
return DateTime.MinValue;
}
using (var stream = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.None))
{
if(stream.Length == 0)
{
return DateTime.MinValue;
}
using (var reader = new BinaryReader(stream))
{
return DateTime.FromBinary(reader.ReadInt64());
};
}
}
/// <summary>
/// overwrites the existing central file and writes the current time into it.
/// </summary>
public void Signal()
{
LastSignal = DateTime.Now;
using (var stream = new FileStream(FilePath, FileMode.Create, FileAccess.Write, FileShare.None))
{
using (var writer = new BinaryWriter(stream))
{
writer.Write(LastSignal.ToBinary());
}
}
}
/// <summary>
/// returns true if the file signal has changed, otherwise false.
/// </summary>
public bool CheckIfSignalled()
{
var signal = GetSignalTimeStamp();
var signalTimestampChanged = LastSignal != signal;
LastSignal = signal;
return signalTimestampChanged;
}
}
一些测试:
[TestMethod]
public void TestSignal()
{
var fileSignal = new FileSignal(Path.GetTempFileName());
var fileSignal2 = new FileSignal(fileSignal.FilePath);
Assert.IsFalse(fileSignal.CheckIfSignalled());
Assert.IsFalse(fileSignal2.CheckIfSignalled());
Assert.AreEqual(fileSignal.LastSignal, fileSignal2.LastSignal);
fileSignal.Signal();
Assert.IsFalse(fileSignal.CheckIfSignalled());
Assert.AreNotEqual(fileSignal.LastSignal, fileSignal2.LastSignal);
Assert.IsTrue(fileSignal2.CheckIfSignalled());
Assert.AreEqual(fileSignal.LastSignal, fileSignal2.LastSignal);
Assert.IsFalse(fileSignal2.CheckIfSignalled());
}
只需使用File.GetLastWriteTime即可。该页面上有一个示例,显示了如何使用它。