2010-07-29 12 views
38

Sto cercando un modo per vedere quando un file è stato modificato l'ultima volta in C#. Ho pieno accesso al file.Controllo dell'ultima modifica di un file in C# su sistema operativo Windows

+0

possibile duplicato di [Come ottenere data di modifica da file in C#] (http://stackoverflow.com/questions/1185378/how-to-get -modificato-data-da-file-in-c-sharp) – nawfal

+0

Il problema nel link sopra è per un caso più specifico ma sono d'accordo - la risposta accettata qui è menzionata in quella domanda. – Candyfloss

risposta

74

System.IO.File.GetLastWriteTime è quello che ti serve.

+0

o eventualmente anche [System.IO.File.GetLastWriteTimeUtc] (https://msdn.microsoft.com/en-us/library/system.io.file.getlastwritetimeutc (v = vs.110) .aspx) –

48

Si desidera semplicemente il metodo statico File.GetLastWriteTime.

Esempio:

DateTime lastModified = System.IO.File.GetLastWriteTime("C:\foo.bar"); 

Console.WriteLine(lastModified.ToString("dd/MM/yy HH:mm:ss")); 
+0

Voto superiore per prendersi il tempo per includere un esempio di codice. – PhilNicholas

14

Essere consapevoli del fatto che la funzione File.GetLastWriteTime non sempre funziona come previsto, i valori vengono a volte non istantaneamente aggiornati dal sistema operativo. Potresti ottenere un vecchio Timestamp, anche se il file è stato modificato in precedenza.

Il comportamento può variare tra le versioni del sistema operativo. Ad esempio, questo test di unità ha funzionato bene ogni volta sulla mia macchina per sviluppatori, ma fallisce sempre sul nostro server di build.

[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)); 
    } 

Vedi File.GetLastWriteTime seems to be returning 'out of date' value

Le opzioni disponibili:

a) vivere con le omissioni occasionali.

b) Creare un componente attivo che realizzi il modello di osservatore (ad esempio una struttura client del server TCP), comunicando direttamente le modifiche anziché scrivere/leggere i file. Veloce e flessibile, ma un'altra dipendenza e un possibile punto di errore (e un po 'di lavoro, ovviamente).

c) Garantire il processo di segnalazione sostituendo il contenuto di un file di segnale dedicato che altri processi leggono regolarmente. Non è così intelligente in quanto è una procedura di polling e ha un sovraccarico maggiore rispetto a chiamare File.GetLastWriteTime, ma se non controlla il contenuto da troppe posizioni troppo spesso, farà il lavoro.

/// <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; 
    } 
} 

Alcuni test per esso:

[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()); 
    } 
Problemi correlati