Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1041 connectés 

  FORUM HardWare.fr
  Programmation
  C#/.NET managed

  C# - FileCopy

 



 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

C# - FileCopy

n°1952855
7ptik
Posté le 23-12-2009 à 17:20:18  profilanswer
 

Bonjour,
 
Je suis débutant en C#; et en train de travailler sur une appli console chargé de copier plusieurs fichiers d'un dossier vers un autre. J'essaye vainement d'afficher un pourcentage ou autre indicateur de la progression de la copy. (FileSystemWatcher, StopWatch). File.copy ne permet que de connaitre la taille avant après mais pas pendant. Je ne souhaite pas utiliser de P/Invoke
Je me suis alors orienté vers la copy via Stream avec une taille de buffer.  
J'arrive à copier un fichier vers une destination avec une taille de 1024 par exemple mais je n'arrive pas à trouver un moyen de récuperer la taille de l'OutSream disons par exemple tout les 1/100 de la taille du fichier. Le but serait d'afficher un "=" ou % à chaque fois que la taille de l'Outstream a augmenté d'un bloc de 6MO pour un fichier de 600MO par exemple.
 
Si quelqu'un peut m'aider ou a déjà eu affaire à cà ?!
 
Merci  

mood
Publicité
Posté le 23-12-2009 à 17:20:18  profilanswer
 

n°1953007
Tamahome
⭐⭐⭐⭐⭐
Posté le 24-12-2009 à 12:15:36  profilanswer
 

BackgroundWorker !


---------------
Hobby eien /人◕ ‿‿ ◕人\
n°1953212
TotalRecal​l
Posté le 26-12-2009 à 13:10:23  profilanswer
 

Tamahome a écrit :

BackgroundWorker !


L'auteur du thread parle d'appli console, le BGWorker est un composant winform il me semble... Et il ne résoud pas le problème.
 
Si au lieu d'utiliser un simple Copy tu implémentais toi même une écriture tamponnée pas trop bête je pense que tu pourrais très bien gérer la progression de la copie comme tu le souhaites!


---------------
Réalisation amplis classe D / T      Topic .Net - C# @ Prog
n°1953243
TotalRecal​l
Posté le 26-12-2009 à 22:22:48  profilanswer
 

Pareil, c'est aussi ce que j'avais compris, mais il a l'air de dire qu'il n'y arrive pas :D.  
Je voulais juste confirmer que j'aurai suivi (à tort ?) la même direction, et que je ne voyais pas la difficulté, il nous faudrait des détails ou du code...


---------------
Réalisation amplis classe D / T      Topic .Net - C# @ Prog
n°1953437
MagicBuzz
Posté le 28-12-2009 à 16:37:33  profilanswer
 

Un truc de ce genre, non ?

 
Code :
  1. using System;
  2. using System.IO;
  3.  
  4. namespace TestConsole
  5. {
  6.    struct Point
  7.    {
  8.        public int X;
  9.        public int Y;
  10.  
  11.        public Point(int x, int y)
  12.        {
  13.            X = x;
  14.            Y = y;
  15.        }
  16.  
  17.    }
  18.  
  19.    class Program
  20.    {
  21.        static void Main(string[] args)
  22.        {
  23.            Point cpos = new Point(Console.CursorLeft, Console.CursorTop);
  24.  
  25.            FileStream fs = File.OpenRead("c:\\in\\source.dat" );
  26.            FileStream fd = File.Create("c:\\in\\destination.dat" );
  27.            double totallength = (double)fs.Length;
  28.            double filepos = (double)fs.Position;
  29.  
  30.            byte[] buffer = new byte[1024];
  31.  
  32.            int length;
  33.            int percent = 0;
  34.            int oldpercent = 0;
  35.  
  36.            Console.Write("  0 %" );
  37.  
  38.            while ((length = fs.Read(buffer, 0, buffer.Length)) > 0)
  39.            {
  40.                filepos = (double)fs.Position;
  41.                fd.Write(buffer, 0, length);
  42.                percent = (int)((filepos / totallength) * 100);
  43.                if (percent != oldpercent)
  44.                {
  45.                    Console.SetCursorPosition(cpos.X, cpos.Y);
  46.                    Console.Write(string.Format("{0} %", percent).PadLeft(5, ' '));
  47.                    oldpercent = percent;
  48.                }
  49.            }
  50.  
  51.            Console.WriteLine();
  52.            Console.WriteLine("Terminé" );
  53.            Console.ReadKey(true);
  54.        }
  55.    }
  56. }


Message édité par MagicBuzz le 28-12-2009 à 17:41:50
n°1953458
MagicBuzz
Posté le 28-12-2009 à 17:36:01  profilanswer
 

Ben je suis au boulot, mais on a un prestataire très frileux qui nous a tout planté notre projet de migration d'ERP, alors voilà quoi, je suis au chômage technique :D

n°1953463
fred777888​999
Posté le 28-12-2009 à 17:51:13  profilanswer
 

Seul petit reproche a ton MagicSource, je prefere :

Code :
  1. FileStream fs = File.OpenRead(@"c:\in\source.dat" );
  2. FileStream fd = File.Create(@"c:\in\destination.dat" );


a tes doubles \ mais je suppose que c'est une question de gout :)

n°1954215
MagicBuzz
Posté le 31-12-2009 à 12:07:34  profilanswer
 

Just for fun, je me suis amusé à rendre le truc multi-threadé avec une jolie GUI et des performances accrues du coup, puisqu'un buffer de 1 Mo permet de pallier aux lenteurs ponctuelles I/O entre les deux threads consommateurs et producteurs.

 

Program.cs

Code :
  1. using System;
  2. using System.IO;
  3. using AdvancedFileManager;
  4.  
  5.  
  6. namespace TestConsole
  7. {
  8.    class Program
  9.    {
  10.        static void Main(string[] args)
  11.        {
  12.            MainProgram mp = new MainProgram();
  13.            mp.Run();
  14.        }
  15.    }
  16.  
  17.    class MainProgram
  18.    {
  19.        int lineSource = 0;
  20.        int lineDestination = 0;
  21.  
  22.        public MainProgram()
  23.        {
  24.        }
  25.  
  26.        public void Run()
  27.        {
  28.            Console.WriteLine("Lancement des threads..." );
  29.  
  30.            Console.WriteLine();
  31.  
  32.            lineSource = Console.CursorTop;
  33.            lineDestination = lineSource + 1;
  34.  
  35.            AdvancedFileManager.AdvancedFileManager afm = new AdvancedFileManager.AdvancedFileManager();
  36.            afm.SourceFileCopyEvent += new FileCopyEventHandler(afm_SourceFileCopyEvent);
  37.            afm.DestinationFileCopyEvent += new FileCopyEventHandler(afm_DestinationFileCopyEvent);
  38.  
  39.            try
  40.            {
  41.                afm.AsyncCopy(@"c:\in\source.dat", @"c:\in\destination.dat", true);
  42.            }
  43.            catch (Exception e)
  44.            {
  45.                Console.WriteLine("Une erreur s'est produite..." );
  46.                Console.WriteLine(e.Message);
  47.            }
  48.  
  49.            Console.SetCursorPosition(0, lineDestination + 2);
  50.  
  51.            Console.WriteLine("Terminé" );
  52.            Console.ReadKey(true);
  53.        }
  54.  
  55.        void afm_SourceFileCopyEvent(object sender, FileCopyEventArgs e)
  56.        {
  57.            DrawPercent(lineSource, e.Percent, "Source:" );
  58.        }
  59.  
  60.        void afm_DestinationFileCopyEvent(object sender, FileCopyEventArgs e)
  61.        {
  62.            DrawPercent(lineDestination, e.Percent, "Destination:" );
  63.        }
  64.  
  65.        public void DrawPercent(int line, int percent, string prefix)
  66.        {
  67.            lock (this)
  68.            {
  69.                Console.SetCursorPosition(0, line);
  70.                Console.Write("{0} [{1}] {2}%", prefix.PadRight(13, ' '), new string('█', (percent / 5)).PadRight(20, '='), percent.ToString().PadLeft(3, ' '));
  71.            }
  72.        }
  73.    }
  74. }
 

AdvancedFileManager.cs

Code :
  1. using System;
  2. using System.Collections;
  3. using System.IO;
  4. using System.Threading;
  5.  
  6. namespace AdvancedFileManager
  7. {
  8.    public delegate void FileCopyEventHandler(object sender, FileCopyEventArgs e);
  9.  
  10.    public class FileCopyEventArgs : EventArgs
  11.    {
  12.        public int Percent;
  13.  
  14.        public FileCopyEventArgs(int percent)
  15.        {
  16.            Percent = percent;
  17.        }
  18.    }
  19.  
  20.    public class AdvancedFileManager
  21.    {
  22.        public event FileCopyEventHandler SourceFileCopyEvent;
  23.        public event FileCopyEventHandler DestinationFileCopyEvent;
  24.  
  25.        public const int BUFFER_SIZE = 1024;
  26.        public const int QUEUE_SIZE = BUFFER_SIZE * 20;
  27.  
  28.        public void AsyncCopy(string source, string destination, bool overwrite)
  29.        {
  30.            // Usual verifications
  31.            if (!File.Exists(source))
  32.            {
  33.                throw new FileNotFoundException("Source file does not exists!" );
  34.            }
  35.  
  36.            if (File.Exists(destination) && !overwrite)
  37.            {
  38.                throw new Exception("Destination file already exists but overwrite is disabled!" );
  39.            }
  40.  
  41.            Queue queue = new Queue();
  42.  
  43.            // Ajouter les messages d'erreur propre en cas de problème d'accès aux fichiers
  44.            FileProducer Prod = new FileProducer(queue, source);
  45.            FileConsumer Cons = new FileConsumer(queue, destination, Prod.Length);
  46.  
  47.            Prod.FileCopyEvent += new FileCopyEventHandler(Prod_FileCopyEvent);
  48.            Cons.FileCopyEvent += new FileCopyEventHandler(Cons_FileCopyEvent);
  49.  
  50.            Thread Producer = new Thread(new ThreadStart(Prod.ThreadRun));
  51.            Thread Consumer = new Thread(new ThreadStart(Cons.ThreadRun));
  52.  
  53.            try
  54.            {
  55.                Producer.Start();
  56.                Consumer.Start();
  57.  
  58.                Producer.Join();
  59.                Consumer.Join();
  60.            }
  61.            catch
  62.            {
  63.                throw new Exception("Unhandled exception while running threads" );
  64.            }
  65.        }
  66.  
  67.        private void Prod_FileCopyEvent(object sender, FileCopyEventArgs e)
  68.        {
  69.            OnSourceFileCopyNotification(new FileCopyEventArgs(e.Percent));
  70.        }
  71.  
  72.        private void Cons_FileCopyEvent(object sender, FileCopyEventArgs e)
  73.        {
  74.            OnDestinationFileCopyNotification(new FileCopyEventArgs(e.Percent));
  75.        }
  76.  
  77.        protected virtual void OnSourceFileCopyNotification(FileCopyEventArgs e)
  78.        {
  79.            SourceFileCopyEvent(this, e);
  80.        }
  81.  
  82.        protected virtual void OnDestinationFileCopyNotification(FileCopyEventArgs e)
  83.        {
  84.            DestinationFileCopyEvent(this, e);
  85.        }
  86.  
  87.        private class FileProducer
  88.        {
  89.            public double Length;
  90.  
  91.            FileStream fs;
  92.            string filename;
  93.            Queue q;
  94.            int oldPercent = 0, percent = 0;
  95.  
  96.            public event FileCopyEventHandler FileCopyEvent;
  97.  
  98.            public FileProducer(Queue queue, string source)
  99.            {
  100.                q = queue;
  101.                filename = source;
  102.  
  103.                FileInfo fi = new FileInfo(filename);
  104.                Length = (double)fi.Length;
  105.            }
  106.  
  107.            public void ThreadRun()
  108.            {
  109.                fs = File.OpenRead(filename);
  110.  
  111.                byte[] buffer = new byte[BUFFER_SIZE];
  112.                int length;
  113.  
  114.                while ((length = fs.Read(buffer, 0, BUFFER_SIZE)) > 0)
  115.                {
  116.                    
  117.                    Monitor.Enter(q);
  118.  
  119.                    while (q.Count > QUEUE_SIZE)
  120.                    {
  121.                        // Wait until the consummer consume some data in the buffer
  122.                        Monitor.Wait(q);
  123.                    }
  124.  
  125.                    percent = (int)((double)fs.Position / Length * 100);
  126.                    if (percent != oldPercent)
  127.                    {
  128.                        OnFileCopyNotification(new FileCopyEventArgs(percent));
  129.                        oldPercent = percent;
  130.                    }
  131.  
  132.                    if (length < BUFFER_SIZE)
  133.                    {
  134.                        byte[] b = new byte[length];
  135.                        for (int i = 0; i < length; i++)
  136.                        {
  137.                            b[i] = buffer[i];
  138.                        }
  139.                        q.Enqueue(b);
  140.                    }
  141.                    else
  142.                    {
  143.                        q.Enqueue(buffer.Clone());
  144.                    }
  145.  
  146.                    Monitor.Pulse(q);
  147.                    Monitor.Exit(q);
  148.                }
  149.  
  150.                Monitor.Enter(q);
  151.                // Don't care is Queue is full, as it's the last item and it's 0-length
  152.                q.Enqueue(new byte[0]);
  153.                Monitor.Pulse(q);
  154.                Monitor.Exit(q);
  155.  
  156.                fs.Close();
  157.                fs.Dispose();
  158.            }
  159.  
  160.            protected virtual void OnFileCopyNotification(FileCopyEventArgs e)
  161.            {
  162.                FileCopyEvent(this, e);
  163.            }
  164.        }
  165.  
  166.        private class FileConsumer
  167.        {
  168.            FileStream fd;
  169.            string filename;
  170.            Queue q;
  171.            double TotalLength;
  172.            int oldPercent = 0, percent = 0;
  173.  
  174.            public event FileCopyEventHandler FileCopyEvent;
  175.  
  176.            public FileConsumer(Queue queue, string destination, double sourcelength)
  177.            {
  178.                q = queue;
  179.                filename = destination;
  180.                TotalLength = sourcelength;
  181.            }
  182.  
  183.            public void ThreadRun()
  184.            {
  185.                fd = File.Create(filename);
  186.                object o;
  187.                byte[] buffer;
  188.                bool Continue = true;
  189.  
  190.                while (Continue)
  191.                {
  192.                    Monitor.Enter(q);
  193.  
  194.                    if (q.Count == 0)
  195.                    {
  196.                        Monitor.Wait(q);
  197.                    }
  198.  
  199.                    o = q.Dequeue();
  200.                    buffer = (byte[])o;
  201.  
  202.                    if (buffer.Length == 0)
  203.                    {
  204.                        Continue = false;
  205.                    }
  206.                    
  207.                    Monitor.Pulse(q);
  208.                    Monitor.Exit(q);
  209.  
  210.                    if (Continue)
  211.                    {
  212.                        fd.Write(buffer, 0, buffer.Length);
  213.  
  214.                        percent = (int)((double)fd.Position / TotalLength * 100);
  215.                        if (percent != oldPercent)
  216.                        {
  217.                            OnFileCopyNotification(new FileCopyEventArgs(percent));
  218.                            oldPercent = percent;
  219.                        }
  220.                    }
  221.                }
  222.  
  223.                fd.Close();
  224.                fd.Dispose();
  225.            }
  226.  
  227.            protected virtual void OnFileCopyNotification(FileCopyEventArgs e)
  228.            {
  229.                FileCopyEvent(this, e);
  230.            }
  231.        }
  232.    }
  233. }


Message édité par MagicBuzz le 31-12-2009 à 15:29:07
n°1954239
fred777888​999
Posté le 31-12-2009 à 14:11:16  profilanswer
 

:ouch: il devient urgent qu'on te trouve un vrai travail a toi.

n°1954243
MagicBuzz
Posté le 31-12-2009 à 14:18:45  profilanswer
 

En tout cas, à quelques optimisations près, maintenant t'as sous la main un FileCopy asynchrone qui donne des nouvelles en fonction de son avancement à la fois sur le fichier source et le fichier destination :D

 

C'est joli, je m'en lasse pas :D

 

http://img24.imageshack.us/img24/456/filecopy.png


Message édité par MagicBuzz le 31-12-2009 à 14:29:51
mood
Publicité
Posté le 31-12-2009 à 14:18:45  profilanswer
 

n°1954268
MagicBuzz
Posté le 31-12-2009 à 15:30:23  profilanswer
 

T'ain je sais pas ce que c'est que la brouette que j'utilise, mais le disque dur est vachement moins rapides que le serveur de fichier... Sur un réseau encombré à 100 Mb, ça fait peur :o

n°1954743
MagicBuzz
Posté le 04-01-2010 à 11:31:38  profilanswer
 

Ca dépend aussi surtout de l'outil que tu utilises pour effectuer la copie.
En effet, l'Explorateur Windows est une daube infâme en ce qui concerne les performances. Outre la fragmentation (ça, j'y crois pas, car même quand c'est pas fragmenté ça déconne), il passe son temps à accéder à la table d'allocation, et visiblement à y flusher systématiquement toutes les données qu'il écrit dedans. Du coup tout le cache système est inutile. Ensuite, ça semble pas optimisé du tout.
 
Y'a des tas de logiciels en remplacement de l'explorateur Windows qui sont bien plus rapide pour faire ce genre d'actions. (surtout sous Vista, où c'est vraiment devenu catastrophique)

n°1954794
Tamahome
⭐⭐⭐⭐⭐
Posté le 04-01-2010 à 14:15:53  profilanswer
 

Genre SuperCopier :D


---------------
Hobby eien /人◕ ‿‿ ◕人\
n°1954822
MagicBuzz
Posté le 04-01-2010 à 14:40:50  profilanswer
 

(faut noter aussi qu'il faut comparer ce qui est comparable)
 
En effet, je veux pas spécialement me faire l'avocat du diable, mais quand sous Windows Vista tu copies un document, il est réindexé dans la foulé afin que la recherche rapide soit à jour. Eventuellement, le superfetch aussi va se mettre à jour dans la foulée, etc.
Sous Linux, de base, t'as ni superfetch ni indexation qui viennent foutre le bordel et tout ralentir ;)

n°1954857
Tamahome
⭐⭐⭐⭐⭐
Posté le 04-01-2010 à 15:23:29  profilanswer
 

l'indexation ca se désactive hein...


---------------
Hobby eien /人◕ ‿‿ ◕人\
n°1954860
MagicBuzz
Posté le 04-01-2010 à 15:29:01  profilanswer
 

Tout comme on peut en mettre une en place sur un serveur Linux :spamafote:
 
Je dis juste que quand Linux travaille dans le système de fichiers, il fait (en générale) juste ce qu'on lui demande.
 
Windows, lui, il fait généralement tout un tas de trucs et accessoirement, quand il lui reste du temps, il copie le fichier.
 
Mais y'a pas moyen d'en tirer des conclusions genre "le système de fichier de windows est moins performant" ou "linux gère mieux la copie des fichiers". C'est juste qu'ils ne font pas la même chose.
Après, je dis pas qui a raison ou non hein ;) C'est débile que copier un répertoire de 1000 fichiers de 1 Ko mette autant de temps que copier 100 Go dans un seul fichier, je suis parfaitement d'accord.

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C#/.NET managed

  C# - FileCopy

 

Sujets relatifs
[Resolu][C++] Question Architecture avec interface multipleTriangle en C
[C#] (RESOLU) GetSchemaTable trop de champs !Petite aide en C !
[C] Programme simpleProjet Algo C
Projet C[C++] Conversion Unicode à ASCII sous linux
Plus de sujets relatifs à : C# - FileCopy


Copyright © 1997-2018 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR