2008年12月3日水曜日

ファイルの高速コピー

Webサイトのコンテンツを更新するとき、ローカルディスクからWebサーバにアップロード(ファイルのコピー)をしていますが、ファイル数が多くてExplorerじゃとてもとても。
調べたところFastCopyとかコピーツールがありましたが、ふとC#で書いてみたらどうなるんだろう、と。

static void Copy( FileInfo source, FileInfo destination ) {
var src = new FileStream( source.FullName, FileMode.Open, FileAccess.Read, FileShare.None, 4096, true );
var buffer = new byte[ source.Length ];
src.BeginRead( buffer, 0, buffer.Length, rar => {
src.EndRead( rar );
src.Close();
if( destination.Exists )
destination.Attributes &= ~FileAttributes.ReadOnly;
var dst = new FileStream( destination.FullName, FileMode.Create, FileAccess.Write, FileShare.None, 4096, true );
dst.BeginWrite( buffer, 0, buffer.Length, war => {
  dst.EndWrite( war );
dst.Close();
}, null );
}, null );
}
static void Copy( DirectoryInfo source, DirectoryInfo destination ) {
if( !destination.Exists )
destination.Create();
foreach( var src in source.GetDirectories() )
Copy( src, new DirectoryInfo( Path.Combine( destination.FullName, src.Name ) ) );
var srcfiles = source.GetFiles();
foreach( var dst in destination.GetFiles() )
if( !srcfiles.Any( src => String.Equals( src.Name, dst.Name, StringComparison.OrdinalIgnoreCase ) ) )
dst.Delete();
foreach( var src in srcfiles )
Copy( src, new FileInfo( Path.Combine( destination.FullName, src.Name ) ) );
}
static void Main( string[] args ) {
Copy( new DirectoryInfo( args[ 0 ] ), new DirectoryInfo( args[ 1 ] ) );
}

まずはお試しで、属性やタイムスタンプなどは保存しませんが。
で、コピー時間ですがFastCopyが740秒なのに対して、C#は200秒…。
何も考えずに並列でファイルオープンしているためハンドル数やバッファサイズなど問題点はいろいろあるとは思いますが、この所要時間の差はいったい…?!
ちなみにこのコード、途中に1回だけ30秒間ストールが発生しています。この問題を解決すれば更に30秒短くなるはず…。

1 件のコメント:

匿名 さんのコメント...

合計16TBのファル移動作業があり、開始前に1日かけて
Tera Copy とFast Copy、fire file copyを
Win7 64bit環境で試用しました。
(ちなみに、CORE-i875 MEM16GB)

試練は780MBのファイル1個をSATAのHDD同士でコピー
し測定。

結果・・・

WINDOWS標準と差異は5秒程度。
環境に依存するんでいすかね。