2つのフォルダの同期を行うフォルダをコピーする際に、コピー元のファイルがコピー先に存在しないか、コピー先のファイルより新しい場合に限りコピーし、さらに2つのフォルダのファイル構成が同じになるようにミラーリング(同期)する方法を紹介します。 まずフォルダのコピーについては、私のサイトの「フォルダをコピーする」をご覧ください。 ここではこのコードに手を加えることにします。 まず、File.ExistsメソッドとFile.GetLastWriteTimeメソッドを使い、コピー元のファイルがコピー先に存在しないか、またはコピー先のファイルより新しいか調べ、ファイルをコピーするようにします。 さらにミラーリングをするために、コピー先にあってコピー元にないファイルを探して削除するためのメソッド(ここでは"DeleteNotExistFiles")を作成します。 このようにして作成された新たなCopyDirectoryメソッドは次のようなものです。 [VB.NET] 'Imports System.IO 'がソースファイルの一番上に書かれているものとする ''' <summary> ''' ディレクトリをコピーする ''' </summary> ''' <param name="sourceDirName">コピーするディレクトリ</param> ''' <param name="destDirName">コピー先のディレクトリ</param> ''' <param name="newerOnly">新しいファイルのみコピーする</param> ''' <param name="sync">sourceDirNameにないファイルを削除する</param> Public Shared Sub CopyDirectory(ByVal sourceDirName As String, _ ByVal destDirName As String, ByVal newerOnly As Boolean, _ ByVal sync As Boolean) 'コピー先のディレクトリがないときは作る If Not Directory.Exists(destDirName) Then Directory.CreateDirectory(destDirName) '属性もコピー File.SetAttributes(destDirName, File.GetAttributes(sourceDirName)) End If 'コピー先のディレクトリ名の末尾に"\"をつける If destDirName.Chars((destDirName.Length - 1)) <> _ Path.DirectorySeparatorChar Then destDirName = destDirName + Path.DirectorySeparatorChar End If 'コピー元のディレクトリにあるファイルをコピー Dim files As String() = Directory.GetFiles(sourceDirName) Dim f As String For Each f In files Dim destFileName As String = destDirName + Path.GetFileName(f) 'コピー先にファイルが存在し、 'コピー元より更新日時が古い時はコピーする If Not newerOnly Or _ Not File.Exists(destFileName) Or _ File.GetLastWriteTime(destFileName) < _ File.GetLastWriteTime(f) Then File.Copy(f, destFileName, True) End If Next f 'コピー先にあってコピー元にないファイルを削除 If sync Then DeleteNotExistFiles(sourceDirName, destDirName) End If 'コピー元のディレクトリにあるディレクトリについて、 '再帰的に呼び出す Dim dirs As String() = Directory.GetDirectories(sourceDirName) Dim dir As String For Each dir In dirs CopyDirectory(dir, destDirName + Path.GetFileName(dir), _ newerOnly, sync) Next dir End Sub ''' <summary> ''' destDirNameにありsourceDirNameにないファイルを削除する ''' </summary> ''' <param name="sourceDirName">比較先のフォルダ</param> ''' <param name="destDirName">比較もとのフォルダ</param> Private Shared Sub DeleteNotExistFiles( _ ByVal sourceDirName As String, ByVal destDirName As String) 'destDirNameにありsourceDirNameにないファイルを削除する Dim files As String() = Directory.GetFiles(destDirName) Dim f As String For Each f In files If Not File.Exists(Path.Combine( _ sourceDirName, Path.GetFileName(f))) Then File.Delete(f) End If Next f 'destDirNameにありsourceDirNameにないフォルダを削除する Dim folders As String() = Directory.GetDirectories(destDirName) Dim folder As String For Each folder In folders If Not Directory.Exists(Path.Combine( _ sourceDirName, Path.GetFileName(folder))) Then Directory.Delete(folder, True) End If Next folder End Sub [C#] //using System.IO; //がソースファイルの一番上に書かれているものとする /// <summary> /// ディレクトリをコピーする /// </summary> /// <param name="sourceDirName">コピーするディレクトリ</param> /// <param name="destDirName">コピー先のディレクトリ</param> /// <param name="newerOnly">新しいファイルのみコピーする</param> /// <param name="sync">sourceDirNameにないファイルを削除する</param> public static void CopyDirectory( string sourceDirName, string destDirName, bool newerOnly, bool sync) { //コピー先のディレクトリがないときは作る if (!Directory.Exists(destDirName)) { Directory.CreateDirectory(destDirName); //属性もコピー File.SetAttributes(destDirName, File.GetAttributes(sourceDirName)); } //コピー先のディレクトリ名の末尾に"\"をつける if (destDirName[destDirName.Length - 1] != Path.DirectorySeparatorChar) destDirName = destDirName + Path.DirectorySeparatorChar; //コピー元のディレクトリにあるファイルをコピー string[] files = Directory.GetFiles(sourceDirName); foreach (string file in files) { string destFileName = destDirName + Path.GetFileName(file); //コピー先にファイルが存在し、 //コピー元より更新日時が古い時はコピーする if (!newerOnly || !File.Exists(destFileName) || File.GetLastWriteTime(destFileName) < File.GetLastWriteTime(file)) { File.Copy(file, destFileName, true); } } //コピー先にあってコピー元にないファイルを削除 if (sync) DeleteNotExistFiles( sourceDirName, destDirName); //コピー元のディレクトリにあるディレクトリについて、 //再帰的に呼び出す string[] dirs = Directory.GetDirectories(sourceDirName); foreach (string dir in dirs) CopyDirectory(dir, destDirName + Path.GetFileName(dir), newerOnly, sync); } /// <summary> /// destDirNameにありsourceDirNameにないファイルを削除する /// </summary> /// <param name="sourceDirName">比較先のフォルダ</param> /// <param name="destDirName">比較もとのフォルダ</param> private static void DeleteNotExistFiles( string sourceDirName, string destDirName) { //destDirNameにありsourceDirNameにないファイルを削除する string[] files = Directory.GetFiles(destDirName); foreach (string file in files) { if (!File.Exists(Path.Combine( sourceDirName, Path.GetFileName(file)))) File.Delete(file); } //destDirNameにありsourceDirNameにないフォルダを削除する string[] folders = Directory.GetDirectories(destDirName); foreach (string folder in folders) { if (!Directory.Exists(Path.Combine( sourceDirName, Path.GetFileName(folder)))) Directory.Delete(folder, true); } } 次に使用法を示します。フォルダ"C:\test1"内の更新されたファイルをフォルダ"C:\test2"にコピーし、ミラーリングを行うには、次のようにします。
[VB.NET]
CopyDirectory("C:\test1", "C:\test2", True, True)
[C#]
CopyDirectory("C:\\test1", "C:\\test2", true, true);
(この記事は、「.NETプログラミング研究 第48号」で紹介したものを基にしています。) 注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。
|
|
Copyright 2002-2008 DOBON!. All rights reserved.
|