20

私は(ある種の)バックアップソリューションを書いています。C:\ の場所からファイルをコピーし、Z:\ の場所に貼り付けるだけです。

速度が速いことを確認するために、コピーして貼り付ける前に、元のファイルが存在するかどうかを確認します。その場合、いくつかの「計算」を実行して、コピーを続行する必要があるかどうか、またはバックアップ ファイルが最新かどうかを判断します。私が難しいと思っているのはこれらの計算です。

元々、ファイルサイズを比較しましたが、ファイルを変更して同じサイズになる可能性が非常に高いため、これでは十分ではありません (たとえば、文字 C をメモ帳に保存すると、文字 T を保存した場合と同じサイズになります)。 )。

したがって、変更日が異なるかどうかを調べる必要があります。現時点では、FileInfoクラスを使用してファイル情報を取得していますが、すべてのフィールドを確認した後、適切と思われるものは何もありません。

変更されたファイルをコピーしていることを確認するにはどうすればよいですか?

編集 SOでMD5チェックサムを使用するという提案を見ましたが、比較しているファイルの一部が最大10GBになるため、これが問題になる可能性があるのではないかと心配しています

4

6 に答える 6

23

変更された日付で行くことは信頼できません - コンピュータの時計は、同期したり、手動で調整したりすると、逆戻りする可能性があります。一部のプログラムは、ファイルの変更またはコピー時に、変更日の管理に関して適切に動作しない場合があります。

アーカイブ ビットを使用することは、制御された環境では機能する可能性がありますが、アーカイブ ビットを使用する別のソフトウェアが実行されている場合はどうなるでしょうか?

Windows アーカイブ ビットは悪であり、停止する必要があります

(ほぼ) 完全な信頼性が必要な場合は、SHA1 などの適切なハッシュ関数を使用して、最後にバックアップしたバージョンのハッシュ値を保存し、ハッシュ値が変更された場合は、新しいコピーをアップロードする必要があります。

SHA1 クラスと下部のコード サンプルを次に示します。

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

ファイルバイトを実行して、ハッシュ値を保存するだけです。FileStream特に大きなファイルの場合、メモリ使用量を減らすために、バイト配列を使用してファイルをメモリにロードする代わりに、 a を渡します。

これをさまざまな方法で変更日と組み合わせて、速度と信頼性のために必要に応じてプログラムを微調整できます。たとえば、ほとんどのバックアップの変更日を確認し、システムがアイドル状態のときに実行されるハッシュ チェッカーを定期的に実行して、何も見逃していないことを確認できます。変更日が変更されても、ファイルの内容は同じ (つまり、同じデータで上書きされた) 場合があります。この場合、ハッシュを再計算した後にファイル全体を再送信することを避け、それがまだ同じであることに気付くことができます。

ほとんどのバージョン管理システムは、ハッシュと変更日を組み合わせた何らかのアプローチを使用しています。

フル バックアップを実行して毎回すべてのデータを送信したくない場合は、一般に、パフォーマンスと信頼性の間で妥協した何らかのリスク管理がアプローチに含まれます。このため、時々「完全バックアップ」を行うことが重要です。

于 2012-10-22T15:36:22.207 に答える
20

ハッシュでファイルを比較できます。

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

コンテンツが変更された場合、ハッシュは異なります。

于 2012-10-22T15:41:02.177 に答える
12

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);
于 2012-10-22T15:33:25.393 に答える
1

通常、ファイル アーカイブ フラグは、ファイルのバックアップが必要かどうかを確認するためにバックアップ プログラムによって使用されます。Windows がファイルを変更または作成すると、アーカイブ フラグが設定されます (こちらを参照)。ファイルのバックアップが必要かどうかを判断するために、アーカイブ フラグが設定されているかどうかを確認します。

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

ファイルをバックアップした後、アーカイブ フラグをクリアします。

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

これは、他のプログラム (システム バックアップ ソフトウェアなど) がアーカイブ フラグをクリアしていないことを前提としています。

于 2012-10-22T15:54:40.240 に答える
1

一般的に言えば、ファイルが変更されたかどうかの追跡は OS に任せます。

使用する場合:

File.GetAttributes

アーカイブ フラグを確認すると、ファイルが最後にアーカイブされてから変更されたかどうかがわかります。コピーが完了したら、XCOPY などでこのフラグをリセットすると思いますが、自分で処理する必要があるかもしれません。

以下を使用して、DOS でフラグを簡単にテストできます。

dir /aa yourfilename

または、Windows エクスプローラーで属性列を追加するだけです。

于 2012-10-22T15:50:00.960 に答える
0

この記事から Crc32 クラスを取得し ます C# および .NET での CRC-32 の計算

この関数にファイル パスを渡します... CRC 値を返します... 既に存在するファイルと比較します... CRC が異なる場合、ファイルは変更されます。

internal Int32 GetCRC(string filepath)
{
    Int32 ret = 0;
    StringBuilder hash = new StringBuilder();
    try
    {
        Crc32 crc32 = new Crc32();
                
        using (System.IO.FileStream fs = File.Open(filepath, FileMode.Open, FileAccess.Read, FileShare.None))
            foreach (byte b in crc32.ComputeHash(fs)) hash.Append(b.ToString("x2").ToLower());
                
        ret = Int32.Parse(hash.ToString(), System.Globalization.NumberStyles.HexNumber);
    }
    catch (Exception ex)
    {
        string msg = (ex.InnerException == null) ? ex.Message : ex.InnerException.Message;
        Console.WriteLine($"FILE ERROR: {msg}");
        
        ret = 0;
    }
    finally
    {
        hash.Clear();
        hash = null;
    }
            
    return ret;
}
于 2021-09-03T19:01:10.307 に答える