Hi all
Comment peut on avoir des infos sur la progression de la copie d 'un gros fichier ? et par exemple le taux de transfert ...
Thx
Hi all
Comment peut on avoir des infos sur la progression de la copie d 'un gros fichier ? et par exemple le taux de transfert ...
Thx
Bonjour,
Si tu utilises File.Copy (ou approchant), ce n'est selon moi pas possible car la méthode ne fournir pas ce genre de retour.
Pour ce faire il faut créer ta propre méthode de copie fournissant des retours sur son avancement (mais cela doit déjà exister donc avec un peu de recherche cela doit être trouvable même sur ce forum)
Ok merci !
Je suis en train de chercher ; pour le moment rien trouve
Bonjour,
Je suis pas certain que File.Copy le permette...
Si ça peux t'aider j'avais écris çà il y as quelque temps.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156 public delegate void CopyPercentHandler(object sender, FileCopyPercentEventArgs args); public delegate void TransfertRateHandler(object sender, TransfertRateEventArgs args); public class FileCopy { #region Déclarations public event CopyPercentHandler FileCopyPercentChanged; public event TransfertRateHandler TransfertRateChanged; public string TargetFilePath { get; private set; } public string DestinationFilePath { get; private set; } private int _Percent; public int Percent { get { return _Percent; } private set { _Percent = value; this.OnPercentChanged(new FileCopyPercentEventArgs(value)); } } private double _TransfertRate; public double TransfertRate { get { return _TransfertRate; } private set { _TransfertRate = value; this.OnTransfertRateChanged(new TransfertRateEventArgs(value)); } } #endregion #region Constructeur public FileCopy() { } #endregion #region Méthodes protected virtual void OnPercentChanged(FileCopyPercentEventArgs args) { this.FileCopyPercentChanged(this, args); } protected virtual void OnTransfertRateChanged(TransfertRateEventArgs args) { this.TransfertRateChanged(this, args); } public void Copy(string fileToCopyPath, string fileCopyPath) { try { if (this.Check(fileToCopyPath, fileCopyPath)) { this.TargetFilePath = fileToCopyPath; this.DestinationFilePath = fileCopyPath; this._Percent = 0; byte[] buffer = new byte[2048]; int read = 0; int loopCount = 0; Stopwatch sw = new Stopwatch(); sw.Start(); using (FileStream fsFileToCopy = new FileStream(fileToCopyPath, FileMode.Open)) { using (FileStream fsFileCopy = new FileStream(fileCopyPath, FileMode.CreateNew)) { do { read = fsFileToCopy.Read(buffer, 0, buffer.Length); fsFileCopy.Write(buffer, 0, read); int curentPercent = Convert.ToInt32((fsFileCopy.Length * 100) / fsFileToCopy.Length); if (curentPercent != this._Percent) this.Percent = curentPercent; loopCount++; if (loopCount == 100) { this.TransfertRate = Math.Round(Convert.ToDouble(fsFileCopy.Length / ((double)sw.ElapsedTicks / (double)10000000)), 2); loopCount = 0; } } while (read != 0); } } } } catch (Exception ex) { throw new Exception(ex.Message, ex); } } private bool Check(string fileToCopyPath, string fileCopyPath) { if (!File.Exists(fileToCopyPath)) throw new FileNotFoundException(string.Format("Le fichier {0} est introuvable", fileToCopyPath)); DialogResult dr = DialogResult.Yes; if (File.Exists(fileCopyPath)) dr = MessageBox.Show(string.Format("Le fichier {0} existe déjà, souhaitez-vous le remplacer ?", fileCopyPath), "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (dr == DialogResult.Yes) { File.Delete(fileCopyPath); return true; } else return false; } #endregion } public class FileCopyPercentEventArgs : EventArgs { private readonly int _Percent; public int Percent { get { return _Percent; } } public FileCopyPercentEventArgs(int percent) { this._Percent = percent; } } public class TransfertRateEventArgs : EventArgs { private readonly double _TransfertRate; public double TransfertRate { get { return _TransfertRate; } } public TransfertRateEventArgs(double rate) { this._TransfertRate = rate; } }
de rien par contre attends je viens de me rendre compte d'une "erreur" sur le calcul du transfert rate. Enfin en l'état actuel il donne taux de transfert global du fichier, si tu veux qu'à chaque affichage tu visualise le taux de transfert depuis la dernière visualisation change la méthode Copy par ce qui suit :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 public void Copy(string fileToCopyPath, string fileCopyPath) { try { if (this.Check(fileToCopyPath, fileCopyPath)) { this.TargetFilePath = fileToCopyPath; this.DestinationFilePath = fileCopyPath; this._Percent = 0; byte[] buffer = new byte[2048]; int read = 0; int loopCount = 0; int getRate = 200; Stopwatch sw = new Stopwatch(); sw.Start(); using (FileStream fsFileToCopy = new FileStream(fileToCopyPath, FileMode.Open)) { using (FileStream fsFileCopy = new FileStream(fileCopyPath, FileMode.CreateNew)) { do { read = fsFileToCopy.Read(buffer, 0, buffer.Length); fsFileCopy.Write(buffer, 0, read); int curentPercent = Convert.ToInt32((fsFileCopy.Length * 100) / fsFileToCopy.Length); if (curentPercent != this._Percent) this.Percent = curentPercent; loopCount++; if (loopCount == getRate) { this.TransfertRate = Math.Round(Convert.ToDouble((buffer.Length * getRate) / ((double)sw.ElapsedTicks / (double)10000000)), 2); loopCount = 0; sw.Reset(); sw.Start(); } } while (read != 0); } } } } catch (Exception ex) { throw new Exception(ex.Message, ex); } }
Salut Toute le monde,
je suis interesee de ce sujet,
mais j'ai ouvrir un nouveau Class dans mon windows application projet et j'ai fais copy toute le classe avec la methode reglee du Copy et j'ai fait Using System.IO;
mais : TargetFilePath ,DestinationFilePath ,_Percent,TransfertRate, ce sont de variables ou des quoi ? textbox ????
et stop watch est un timer ?
Merci D'avance !
@Seth77
J'aurais plutôt regardé du côté de CopyFileEx (copie de fichiers avec callback de progression) our MoveFileWithProgress (déplacement de fichiers et répertoires avec callback de progression). Ce sont des API Win32 mais rien de très sorcier.
@Genius
Ce sont des variables membres de la classe, oui.
StopWatch sert à mesurer avec précision la durée d'un traitement, voir msdn.
Bien vu DonQuiche, merci, voilà une mise à jour
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328 public delegate void CopyPercentHandler(object sender, CopyPercentEventArgs args); public delegate void TransfertRateHandler(object sender, TransfertRateEventArgs args); public delegate void FinishHandler(object sender, FinishEventArgs args); public class ProgressCopy { #region Déclarations [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool CopyFileEx(string lpExistingFileName, string lpNewFileName, CopyProgressRoutine lpProgressRoutine, IntPtr lpData, ref Int32 pbCancel, CopyFileFlags dwCopyFlags); [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] static extern bool MoveFileWithProgress(string lpExistingFileName, string lpNewFileName, CopyProgressRoutine lpProgressRoutine, IntPtr lpData, MoveFileFlags dwCopyFlags); enum CopyProgressResult : uint { PROGRESS_CONTINUE = 0, PROGRESS_CANCEL = 1, PROGRESS_STOP = 2, PROGRESS_QUIET = 3 } enum CopyProgressCallbackReason : uint { CALLBACK_CHUNK_FINISHED = 0x00000000, CALLBACK_STREAM_SWITCH = 0x00000001 } [Flags] enum CopyFileFlags : uint { COPY_FILE_FAIL_IF_EXISTS = 0x00000001, COPY_FILE_RESTARTABLE = 0x00000002, COPY_FILE_OPEN_SOURCE_FOR_WRITE = 0x00000004, COPY_FILE_ALLOW_DECRYPTED_DESTINATION = 0x00000008 } [Flags] enum MoveFileFlags : uint { MOVE_FILE_REPLACE_EXISTSING = 0x00000001, MOVE_FILE_COPY_ALLOWED = 0x00000002, MOVE_FILE_DELAY_UNTIL_REBOOT = 0x00000004, MOVE_FILE_WRITE_THROUGH = 0x00000008, MOVE_FILE_CREATE_HARDLINK = 0x00000010, MOVE_FILE_FAIL_IF_NOT_TRACKABLE = 0x00000020 } delegate CopyProgressResult CopyProgressRoutine ( long TotalFileSize, long TotalBytesTransferred, long StreamSize, long StreamBytesTransferred, uint dwStreamNumber, CopyProgressCallbackReason dwCallbackReason, IntPtr hSourceFile, IntPtr hDestinationFile, IntPtr lpData ); public string TargetPath { get; private set; } public string DestinationPath { get; private set; } private int _Percent; public int Percent { get { return _Percent; } private set { _Percent = value; this.OnPercentChanged(new CopyPercentEventArgs(value, this.totalTransfered)); } } private double _TransfertRate; public double TransfertRate { get { return _TransfertRate; } private set { _TransfertRate = value; this.OnTransfertRateChanged(new TransfertRateEventArgs(value, this.totalTransfered)); } } public event CopyPercentHandler CopyPercentChanged; public event TransfertRateHandler TransfertRateChanged; public event FinishHandler Finished; long lastTransfered; long totalTransfered; int pbCancel; TimeSpan totalElapsed; private TimeSpan _NotificationFrequency; private DateTime _LastNotification; Stopwatch sw = new Stopwatch(); #endregion #region Constructeur public ProgressCopy() { this._NotificationFrequency = TimeSpan.FromSeconds(1); } public ProgressCopy(TimeSpan notificationFrequency) { this._NotificationFrequency = notificationFrequency; } #endregion #region Méthodes public void Copy(string targetFilePath, string destinationFilePath) { if (Check(targetFilePath, destinationFilePath)) { this.Init(); this.CopyF(targetFilePath, destinationFilePath); } } public void Move(string targetFilePath, string destinationFilePath) { if (Check(targetFilePath, destinationFilePath)) { this.Init(); this.MoveF(targetFilePath, destinationFilePath); } } private void Init() { this.lastTransfered = 0; this.totalTransfered = 0; this.totalElapsed = new TimeSpan(); this._LastNotification = DateTime.Now; this.InitSw(); } private void InitSw() { sw.Reset(); sw.Start(); } private void MoveF(string oldF, string newF) { bool success = MoveFileWithProgress(oldF, newF, new CopyProgressRoutine(this.CopyProgressCallback), IntPtr.Zero, MoveFileFlags.MOVE_FILE_COPY_ALLOWED); if (success) this.OnFinished(new FinishEventArgs(Math.Round((double)this.totalTransfered / this.totalElapsed.TotalMilliseconds, 2), this.totalElapsed)); else { Win32Exception win_ex = new Win32Exception(Marshal.GetLastWin32Error()); throw new Exception(string.Format("Erreur durant la copie du répertoire {0} vers {1}\n{2}", oldF, newF, win_ex.Message)); } } private void CopyF(string oldFile, string newFile) { bool success = CopyFileEx(oldFile, newFile, new CopyProgressRoutine(this.CopyProgressCallback), IntPtr.Zero, ref pbCancel, CopyFileFlags.COPY_FILE_RESTARTABLE); if (success) this.OnFinished(new FinishEventArgs(Math.Round((double)this.totalTransfered / this.totalElapsed.TotalMilliseconds, 2), this.totalElapsed)); else { Win32Exception win_ex = new Win32Exception(Marshal.GetLastWin32Error()); throw new Exception(string.Format("Erreur durant la copie du fichier {0} vers {1}\n{2}", oldFile, newFile, win_ex.Message)); } } private CopyProgressResult CopyProgressCallback(long total, long transferred, long streamSize, long StreamByteTrans, uint dwStreamNumber, CopyProgressCallbackReason reason, IntPtr hSourceFile, IntPtr hDestinationFile, IntPtr lpData) { long currentElapsedTicks = sw.ElapsedTicks; DateTime currentDate = DateTime.Now; this.totalElapsed += TimeSpan.FromTicks(currentElapsedTicks); this.totalTransfered += transferred; if (this._LastNotification + this._NotificationFrequency < currentDate) { this._LastNotification = currentDate; int currentPercent = Convert.ToInt32((transferred * 100) / total); if (currentPercent != this._Percent) this.Percent = currentPercent; this.TransfertRate = Math.Round(Convert.ToDouble((transferred - this.lastTransfered) / ((double)currentElapsedTicks / (double)10000000)), 2); } this.lastTransfered = transferred; this.InitSw(); return CopyProgressResult.PROGRESS_CONTINUE; } private bool Check(string targetPath, string destinationPath) { DialogResult dr = DialogResult.Yes; if (string.IsNullOrEmpty(Path.GetExtension(targetPath))) { if (!Directory.Exists(targetPath)) throw new DirectoryNotFoundException(string.Format("Le dossier {0} est introuvable", targetPath)); if (Directory.Exists(destinationPath)) { dr = MessageBox.Show(string.Format("Le dossier {0} existe déjà, souhaitez-vous le remplacer ?", destinationPath), "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (dr == DialogResult.Yes) Directory.Delete(destinationPath); else return false; } return true; } else { if (!File.Exists(targetPath)) throw new FileNotFoundException(string.Format("Le fichier {0} est introuvable", targetPath)); if (File.Exists(destinationPath)) { dr = MessageBox.Show(string.Format("Le fichier {0} existe déjà, souhaitez-vous le remplacer ?", destinationPath), "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (dr == DialogResult.Yes) File.Delete(destinationPath); else return false; } return true; } } protected virtual void OnPercentChanged(CopyPercentEventArgs args) { this.CopyPercentChanged(this, args); } protected virtual void OnTransfertRateChanged(TransfertRateEventArgs args) { this.TransfertRateChanged(this, args); } protected virtual void OnFinished(FinishEventArgs args) { this.Finished(this, args); } #endregion } public class FinishEventArgs : EventArgs { private readonly double _GlobalTransfertRate; public double GlobalTransfertRate { get { return _GlobalTransfertRate; } } private readonly TimeSpan _Duration; public TimeSpan Duration { get { return _Duration; } } public FinishEventArgs(double transfertRate, TimeSpan duration) { this._GlobalTransfertRate = transfertRate; this._Duration = duration; } } public class TransfertRateEventArgs : EventArgs { private readonly double _TransfertRate; public double TransfertRate { get { return _TransfertRate; } } private readonly long _Transfered; public long Transfered { get { return _Transfered; } } public TransfertRateEventArgs(double rate, long transfered) { this._TransfertRate = rate; this._Transfered = transfered; } } public class CopyPercentEventArgs : EventArgs { private readonly int _Percent; public int Percent { get { return _Percent; } } private readonly long _Transfered; public long Transfered { get { return _Transfered; } } public CopyPercentEventArgs(int percent, long transfered) { this._Percent = percent; this._Transfered = transfered; } }
tu devrais mettre le code en partie Contribution
+1, c'est la meilleure solution a priori...
En plus la lib Dvp.NET contient des wrappers .NET pour ces API, donc c'est encore plus facile à utiliser :
FileCopyOperation
FileMoveOperation
Ca s'utilise comme ça :
Le taux de transfert n'est pas géré, mais c'est pas trop compliqué à ajouter dans le handler de l'évènement...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 var copy = new FileCopyOperation(source, destination); copy.ProgressChanged += copy_ProgressChanged; copy.Execute(); ... void copy_ProgressChanged(object sender, FileOperationProgressEventArgs e) { Console.WriteLine( "Copié {0} octets sur {1} ({2}%)", e.TransferredBytes, e.TotalBytes, e.PercentDone); }
Pas de questions techniques par MP ! Le forum est là pour ça...
Tutoriels : Les nouveautés de C# 6 - Accès aux données avec Dapper - Extraction de données de pages web à l'aide de HTML Agility Pack - La sérialisation XML avec .NET (Aller plus loin) - Les markup extensions en WPF
Bonjour, je pense avoir trouvé une erreur dans le calcul de la vitesse de transfert.
L'auteur de la source utilise la classe StopWatch qui donne le temps entre deux impulsions du processeur la vitesse donnée est 40Mo/s.
En faisant mon propre calcul avec 2 DateTime je trouve une vitesse à 10Mo/s.
Je ne sais pas trop l'expliquer mais le calcul de la vitesse ne prend pas en compte le nombre de processeur de la machine.
Pour ceux que ça intéresse remplacez dans la fonction CopyProgressResult CopyProgressCallback(........) :
par
Code : Sélectionner tout - Visualiser dans une fenêtre à part this.TransfertRate = Math.Round(Convert.ToDouble((transferred - this.m_lastTransfered) / ((double)currentElapsedTicks / (double)10000000)), 2)
Attention la vitesse est exprimée en octets/s.
Code : Sélectionner tout - Visualiser dans une fenêtre à part this.TransfertRate = Convert.ToDouble((transferred - this.m_lastTransfered) / ((double)currentElapsedTicks / (double)10000000) / Environment.ProcessorCount);
Il est également possible de connaitre le volume de données restant à transférer :
A+
Code : Sélectionner tout - Visualiser dans une fenêtre à part this.m_Restant = total - transferred;
Ca me parait bizarre ton histoire... je ne vois pas très bien ce que le nombre de processeurs vient faire là-dedans. Une copie de fichier c'est une opération presque purement IO, ça n'utilise quasiment pas le processeur (et encore moins plusieurs processeurs).
Il y a peut-être une erreur dans ton calcul à base de DateTime... ou alors il y en a une dans le calcul à base de Stopwatch. DateTime est beaucoup moins précis que Stopwatch, mais en l'occurrence je ne pense pas que ça suffise à expliquer la différence
Pas de questions techniques par MP ! Le forum est là pour ça...
Tutoriels : Les nouveautés de C# 6 - Accès aux données avec Dapper - Extraction de données de pages web à l'aide de HTML Agility Pack - La sérialisation XML avec .NET (Aller plus loin) - Les markup extensions en WPF
Bon ok à y réfléchir je ne vois pas bien non plus pourquoi cela dépendrait du nombre de processeur... j'ai fais un raccourci dans ma tête
Mais alors comment expliquer le facteur 4 entre la vitesse trouvée par le code erroné et la vitesse calculée par la copie Windows de base ?
Cela dit je vais tester sur une machine 2 coeurs. On ne sait jamais.
Bon toujours aucune idée de ce qui cloche dans le code original mais voila selon moi le calcul correct de la vitesse de transfert :
La durée (en seconde) entre deux appels à la fonction est donnée par le nombre de nbre de ticks divisé par la fréquence (nombre de ticks par seconde)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 double duration = (double)currentElapsedTicks / (double)Stopwatch.Frequency; this.TransfertRate = Convert.ToDouble((transferred - this.m_lastTransfered) / duration);
La vitesse de transfert (en octets / sec) équivaut donc au nombre d'octets transférés entre deux appels divisé par la durée entre deux appels.
Pas de questions techniques par MP ! Le forum est là pour ça...
Tutoriels : Les nouveautés de C# 6 - Accès aux données avec Dapper - Extraction de données de pages web à l'aide de HTML Agility Pack - La sérialisation XML avec .NET (Aller plus loin) - Les markup extensions en WPF
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager