Top / SimpleSync
壊れかけたハードディスクからコピーできるファイルだけ取り出すため、エラーログ採取機能が付いたコピーソフトをでっち上げました。 言い訳 †この手のソフトはたくさんあります。なぜわざわざ作ったかというと、コピーしながら例外のログを採取するだけなので、イメージ通りのものを探すよりも作った方が手っ取り早かったからです。 マルチスレッド化により複雑になってしまいました。
ダウンロード †
過去のリリース †
実装 †実装で使っているテクニックを紹介します。書式は煩雑な印象がありますが過渡的なもので、C# 3.0ではもっと簡潔なものになるようです。 匿名メソッド †最初にファイルサイズをチェックしてからコピーを開始します。チェックとコピーの処理はどちらも再帰的にディレクトリをたどっているため、再帰処理は共通化して、異なる部分だけを匿名メソッドで渡すようにしました。今流行のクロージャ的な書き方です。ローカル変数がそのまま使えて便利です。 long size = 0, totalSize = 0, count = 0, totalCount = 0; CompareFolder(di1, di2, "", delegate(FileInfo fi1, FileInfo fi2) { SetProgressText("--- / {0:#,##0} MB , --- / {1:#,##0} 個", totalSize / 1024 / 1024, totalCount); if (fi1 == null) return; totalSize += fi1.Length; totalCount++; }); if (totalSize == 0) totalSize = 1; CompareFolder(di1, di2, "", delegate(FileInfo fi1, FileInfo fi2) { CopyFile(fi1, fi2, delegate(long pos) { SetProgressText( "{0:#,##0} / {1:#,##0} MB ({2} %) , {3:#,##0} / {4:#,##0} 個", (size + pos) / 1024 / 1024, totalSize / 1024 / 1024, size * 100 / totalSize, count, totalCount); }, delegate { size += fi1.Length; count++; }); }); メソッドにブロックを渡すような感じです。元々あった委譲の概念を拡張(この場合は定義のインライン化)して実装されているため、関数型言語のようにアプリオリに実装されているよりも理解しやすいと思いました。 C# 3.0ではラムダ式という簡単な書式が使用できるようになりました。 [C# 2.0] delegate(FileInfo fi1, FileInfo fi2) {} [C# 3.0] (fi1, fi2) => {} 汎用delegate †既存のメソッドをdelegateとして渡すときにキャストをすると簡潔に記述できます。delegateを汎用的に表現しているAction<>を使うと、いちいちdelagateを定義する必要がないため便利です。 private void SetLabelText(Label label, string t) { label.Text = t; } private void SetFolderLabel(string t) { Invoke((Action<Label, string>)SetLabelText, label3, t); } |