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

Dav*_*ave 13 c#

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

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

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

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

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

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

Mik*_*ski 15

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

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

Windows存档位是邪恶的,必须停止

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

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

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

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

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

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

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

  • 这取决于你的系统是如何实现的:)你可以保留数据库的数据,或者你可以做subversion用来做的事情,并在备份的位置内创建一个隐藏目录,其中包含备份的所有文件的哈希值.Subversion离开了它,现在只将数据库保存在版本化目录结构的根目录中的隐藏目录中. (3认同)

Ser*_*kiy 15

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

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

如果内容发生了变化,则哈希值会有所不同.

  • 仅比较最后两个字节是不够的。使用 hash1.SequenceEqual(hash2) 比较所有字节 (2认同)

dsg*_*fin 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);
Run Code Online (Sandbox Code Playgroud)