如果文件已被修改,如何计算?

时间:2012-10-22 15:31:06

标签: c#

我正在编写备份解决方案(各种各样)。只需从位置C:\复制一个文件并将其粘贴到位置Z:\

为确保速度快,在复制和粘贴之前,它会检查原始文件是否存在。如果是这样,它会执行一些“计算”,以确定是否应该继续复制或备份文件是否是最新的。正是这些计算我发现很难。

最初,我比较了文件大小,但这还不够好,因为它很可能更改文件并且大小相同(例如,在记事本中保存字符C的大小与保存时相同)人物T)。

所以,我需要找出修改日期是否不同。目前,我使用FileInfo类获取文件信息,但在查看了所有字段后,似乎没有任何内容适合。

如何检查以确保我正在复制已修改过的文件?

修改  我已经看到有关SO使用MD5校验和的建议,但我担心这可能是一个问题,因为我正在比较的一些文件将高达10GB

5 个答案:

答案 0 :(得分:15)

按修改日期进行操作将不可靠 - 计算机时钟可以在同步或手动调整时倒退。在管理修改日期方面修改或复制文件时,某些程序可能表现不佳。

归档位可能在受控环境中运行,但如果正在运行的其他软件也使用归档位会发生什么?

The Windows archive bit is evil and must be stopped

如果您希望(几乎)完全可靠,那么您应该做的是使用良好的哈希函数(如SHA1)存储上次备份版本的哈希值,如果哈希值发生更改,则上载新副本。

这是SHA1类以及底部的代码示例:

http://msdn.microsoft.com/en-us/library/system.security.cryptography.sha1.aspx

只需通过它运行文件字节并存储哈希值。将FileStream传递给它而不是使用字节数组将文件加载到内存中以减少内存使用量,尤其是对于大文件。

您可以通过各种方式将其与修改日期结合起来,根据需要调整程序的速度和可靠性。例如,您可以检查大多数备份的修改日期,并定期运行在系统空闲时运行的哈希检查程序,以确保没有遗漏任何内容。有时修改日期会改变,但文件内容仍然相同(即被相同数据覆盖),在这种情况下,您可以避免在重新计算哈希值后重新发送整个文件,并意识到它仍然是相同的。

大多数版本控制系统使用某种与哈希和修改日期相结合的方法。

如果您不想进行完整备份并且每次都发送所有数据,那么您的方法通常会涉及某种风险管理,并在性能和可靠性之间进行折衷。由于这个原因,偶尔进行“完全备份”非常重要。

答案 1 :(得分:14)

您可以通过哈希值比较文件:

private byte[] GetFileHash(string fileName)
{
    HashAlgorithm sha1 = HashAlgorithm.Create();
    using(FileStream stream = new FileStream(fileName,FileMode.Open,FileAccess.Read))
      return sha1.ComputeHash(stream);
}

如果内容发生变化,则散列会有所不同。

答案 2 :(得分:9)

您可以查看FileSystemWatcher课程。

  

“此类允许您监视目录以进行更改并触发   某事被修改时的事件。“

然后,您的代码可以处理事件并处理文件。

代码来源 - MSDN:

// Create a new FileSystemWatcher and set its properties.
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = args[1];

/* Watch for changes in LastAccess and LastWrite times, and
   the renaming of files or directories. */
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
   | NotifyFilters.FileName | NotifyFilters.DirectoryName;

// Only watch text files.
watcher.Filter = "*.txt";

// Add event handlers.
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Created += new FileSystemEventHandler(OnChanged);
watcher.Deleted += new FileSystemEventHandler(OnChanged);
watcher.Renamed += new RenamedEventHandler(OnRenamed);

答案 3 :(得分:1)

一般来说,您可以让操作系统负责跟踪文件是否已更改。

如果您使用:

File.GetAttributes

并检查归档标志,这将告诉您文件自上次归档后是否已更改。我相信XCOPY和类似的一旦完成复制后重置此标志,但您可能需要自己处理。

您可以使用以下方法在DOS中轻松测试该标志:

dir /aa yourfilename

或者只是在Windows资源管理器中添加属性列。

答案 4 :(得分:1)

备份程序通常使用文件存档标志来检查文件是否需要备份。当Windows修改或创建文件时,它会设置存档标志(请参阅here)。检查是否设置了归档标志以确定文件是否需要备份:

if ((File.GetAttributes(fileName) & FileAttributes.Archive) == FileAttributes.Archive)
{
    // Archive file.
}

备份文件后,清除存档标志:

File.SetAttributes(fileName, File.GetAttributes(fileName) & ~FileAttributes.Archive);

这假定没有其他程序(例如,系统备份软件)正在清除存档标志。