Search code examples
c#system.io.file

Fastest way to copy files from one directory to another


I need to copy files from one directory to another, depending on the existence of the file name in a table of SQL database.

For this I use the following code:

using(SqlConnection connection = new SqlConnection("datasource or route"))
{

  connection.Open();

  using(SqlCommand cmd = new SqlCommand("SELECT idPic, namePicFile FROM DocPicFiles", connection))
  using (SqlDataReader reader = cmd.ExecuteReader())
  {

    if (reader != null)
    {
      while (reader.Read())
      {
        //picList IS AN ARRAY THAT Contains All the files names in a directory
        if (picList.Any(s => s.Contains(reader["namePicFile"].ToString())))
        {
          File.Copy("theFile  in the Directory or array picList",  "the destiny directory"+ ".jpg", false)
        }
      }
    }
  }
}

Is there any way that this can be done in less time? It takes 1 hour for do that, for 20.876 records.


Solution

  • Since your i/o subsystem is almost certainly the botteneck here, using the parallel task library is probably about as good as it gets:

    static void Main(string[] args)
    {
      DirectoryInfo source      = new DirectoryInfo( args[0] ) ;
      DirectoryInfo destination = new DirectoryInfo( args[1] ) ;
    
      HashSet<string> filesToBeCopied = new HashSet<string>( ReadFileNamesFromDatabase() , StringComparer.OrdinalIgnoreCase ) ;
    
      // you'll probably have to play with MaxDegreeOfParallellism so as to avoid swamping the i/o system
      ParallelOptions options= new ParallelOptions { MaxDegreeOfParallelism = 4 } ;
    
      Parallel.ForEach( filesToBeCopied.SelectMany( fn => source.EnumerateFiles( fn ) ) , options , fi => {
          string destinationPath = Path.Combine( destination.FullName , Path.ChangeExtension( fi.Name , ".jpg") ) ;
          fi.CopyTo( destinationPath , false ) ;
      }) ;
    
    }
    
    public static IEnumerable<string> ReadFileNamesFromDatabase()
    {
      using ( SqlConnection connection = new SqlConnection( "connection-string" ) )
      using ( SqlCommand cmd = connection.CreateCommand() )
      {
        cmd.CommandType = CommandType.Text ;
        cmd.CommandText = @"
          select idPic ,
                 namePicFile
          from DocPicFiles
          " ;
    
        connection.Open() ;
        using ( SqlDataReader reader = cmd.ExecuteReader() )
        {
          while ( reader.Read() )
          {
            yield return reader.GetString(1) ;
          }
        }
        connection.Close() ;
    
      }
    }