Kopiowanie całych folderów z Progressbarem jest nieco trudniejsze niż kopiowanie tylko jednego pliku. Aby użyć File stream’a do kopiowania plików należy zbadać folder w celu ich odnalezienia i określić ile sub folderów znajduje się wewnątrz folderu, następnie zbadać znalezione subfoldery w poszukiwaniu plików i kolejnych subfolderów, trzeba również zachować hierarchie folderów i plików. Stworzyłem algorytm który spełnia te kryteria. Jego opis publikuje poniżej:
Najpierw ułuż elementy tak jak na obrazku poniżej
Następnir dodajemy BackgroundWorker i FolderBrowser x2 do naszej formy
Jeśli wszystko poszło dobrze zobaczymy je w polu pod formą
Zmieniamy tekst poszczególnych elementów tak jak na obrazku
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 |
Public Class Form1 Dim directoryTargetLocation As String 'Selected file path Dim Destinydirectory As String 'Selected dest directory path Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click FolderBrowserDialog1.Description = "Select directory" With FolderBrowserDialog1 If .ShowDialog() = DialogResult.OK Then directoryTargetLocation = .SelectedPath Label1.Text = directoryTargetLocation.ToString End If End With End Sub Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click FolderBrowserDialog2.Description = "Select destiny directory" With FolderBrowserDialog2 If .ShowDialog() = DialogResult.OK Then Destinydirectory = .SelectedPath Label2.Text = Destinydirectory.ToString End If End With End Sub Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork Dim parts As String() = directoryTargetLocation.Split(New Char() {"\"c}) Dim filename As String = parts(parts.Count - 1) 'target folder name Dim dir_path As String = "" 'directory without target folder name For f As Integer = 0 To parts.Count - 2 dir_path += parts(f) + "\" Next Dim copied As Integer = 0 Dim counter As Integer = IO.Directory.GetFiles(directoryTargetLocation, "*.*", IO.SearchOption.AllDirectories).Length 'counts the number of files SetProgressbar(counter, ProgressBar2) 'Sets ProgressBar maximum to number of files setLabelTxt("Copied (0/" + counter.ToString + ")", Label4) 'displays the amount of copied files Dim FolderList As New List(Of String) FolderList.Add(directoryTargetLocation) 'Set first folder Do While True If (BackgroundWorker1.CancellationPending = True) Then 'cancel loop e.Cancel = True Exit Do End If Dim FoldersInsideDirectory As New List(Of String) If FolderList.Count = 0 Then Exit Do 'If there is no folder to copy Exit Do Else For l As Integer = 0 To FolderList.Count - 1 If (BackgroundWorker1.CancellationPending = True) Then 'stop for loop e.Cancel = True Exit For End If Dim sourceDirectoryInfo As New System.IO.DirectoryInfo(FolderList(l)) Dim dest As String = FolderList(l).Replace(dir_path, "") If (Not System.IO.Directory.Exists(Destinydirectory + "\" + dest)) Then 'create subFolder inside directory System.IO.Directory.CreateDirectory(Destinydirectory + "\" + dest) End If Dim fileSystemInfo As System.IO.FileSystemInfo For Each fileSystemInfo In sourceDirectoryInfo.GetFileSystemInfos If (BackgroundWorker1.CancellationPending = True) Then e.Cancel = True Exit For End If Dim destinationFileName As String = System.IO.Path.Combine(Destinydirectory + "\" + dest, fileSystemInfo.Name) If TypeOf fileSystemInfo Is System.IO.FileInfo Then Dim streamRead As New System.IO.FileStream(fileSystemInfo.FullName, System.IO.FileMode.Open) setLabelTxt(fileSystemInfo.FullName.ToString, Label3) Dim streamWrite As New System.IO.FileStream(Destinydirectory + "\" + dest + "\" + fileSystemInfo.Name, IO.FileMode.Create, IO.FileAccess.Write, IO.FileShare.None) Dim lngLen As Long = streamRead.Length - 1 setLabelTxt("Copy bytes : (0/" + (lngLen * 100).ToString + ")", Label5) Dim byteBuffer(1048576) As Byte 'our stream buffer Dim intBytesRead As Integer 'number of bytes read While streamRead.Position < lngLen 'keep streaming until EOF If (BackgroundWorker1.CancellationPending = True) Then e.Cancel = True Exit While End If BackgroundWorker1.ReportProgress(CInt(streamRead.Position / lngLen * 100)) setLabelTxt("Copy bytes : (" + CInt(streamRead.Position).ToString + "/" + (lngLen * 100).ToString + ")", Label5) intBytesRead = (streamRead.Read(byteBuffer, 0, 1048576)) streamWrite.Write(byteBuffer, 0, intBytesRead) End While 'Clean up streamWrite.Flush() streamWrite.Close() streamRead.Close() addProgress(1, ProgressBar2) copied += 1 setLabelTxt("Copied (" + copied.ToString + "/" + counter.ToString + ")", Label4) Else FoldersInsideDirectory.Add(fileSystemInfo.FullName) End If Next Next FolderList.Clear() FolderList = FoldersInsideDirectory End If Loop End Sub Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click Button1.Enabled = False 'button1 block Button2.Enabled = False 'button2 block Button3.Enabled = False BackgroundWorker1.RunWorkerAsync() 'do magic End Sub Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged ProgressBar1.Value = e.ProgressPercentage End Sub Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted If e.Cancelled = True Then MsgBox("Copy canceled!") Else MsgBox("Copy complete!") End If Button1.Enabled = True Button2.Enabled = True Button3.Enabled = True End Sub Private Sub setLabelTxt(ByVal text As String, ByVal lbl As Label) If lbl.InvokeRequired Then lbl.Invoke(New setLabelTxtInvoker(AddressOf setLabelTxt), text, lbl) Else lbl.Text = text End If End Sub Private Delegate Sub setLabelTxtInvoker(ByVal text As String, ByVal lbl As Label) Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click If BackgroundWorker1.IsBusy Then BackgroundWorker1.CancelAsync() End If End Sub Private Sub SetProgressbar(ByVal val As Integer, ByVal progressba As ProgressBar) If progressba.InvokeRequired Then progressba.Invoke(New SetProgressbarInvoker(AddressOf SetProgressbar), val, progressba) Else progressba.Value = 0 progressba.Maximum = val End If End Sub Private Delegate Sub SetProgressbarInvoker(ByVal val As Integer, ByVal progressba As ProgressBar) Private Sub addProgress(ByVal val As Integer, ByVal progressba As ProgressBar) If progressba.InvokeRequired Then progressba.Invoke(New addProgressInvoker(AddressOf addProgress), val, progressba) Else progressba.Value += val End If End Sub Private Delegate Sub addProgressInvoker(ByVal val As Integer, ByVal progressba As ProgressBar) End Class |
10 Komentarzy
Skip to comment form
Nice work ! It’s possible to converte to move folder instead of copy ?
Author
Using this loop you can’t do that. Becouse you don’t manipulate main file, you just read and copy file by byte. FIlestream can’t delete main file. You can add comand „System.IO.File.Delete( FileToDelete )” to the loop, when file has been copied then it will delete it.
how to copy hidden files with this?
thanks.
Author
you can check the file attribute using:
If Not fileSystemInfo.Attributes = Nothing AndAlso fileSystemInfo.Attributes = System.IO.FileAttributes.Hidden Then …
or check directory attribute using the same loop.
Nice Job!!
How to select multiple folders?
Thanks
Author
Hello,
I do not quite understand what you want to do
Try to list all directories using:
For Each Dir As String In Directory.GetDirectories(„your directory”)
” Copy metod
Next
and call copy method for each folders
Fantastic Work, Impressive
Please tell me how do I copy only selected file formats from the source folder to destination folders using your above code, Sometimes 2 destination folders
Ex:
Source Folder have *.dat, *.abq, *.zas, *.slp, *.log, *.zipp, *.mat and *.mno files,
I want to copy only *.abq, *.dat, *.log, and *.mno files to Destination folder ( Sometimes 2 destination folders)
Thank You
Author
Hi,
Thank you for the comment 😀
first you need to define an Array, this will help you easyli manage all extensions:
Dim extensions As String() = {„.abq”, „.dat”, „.log”}
then put a logic below the line 83
83: If TypeOf fileSystemInfo Is System.IO.FileInfo Then
84: If extensions.Contains(fileSystemInfo.Extension) Then
85: …..
That should do the work 😉
But remember to change the file count logic to set the progressbar properly
HI Sir,
I just started learning programing and your code helps me a lot. I was only wondering how to add estimated remaining time and transfer rate of the copying files.
Thank you in advance
Hi Admin,
Thank you, this is awesome. I have customised this after going through the code. However there is one thing which stands out for me, yes this copys every folder (directory) perfectly, but It doesn’t copy Documents (My Documents) directory, yes it copys individual folder within it, but it does copy all of the folder (Directory). With out folders (Directory) no problem. Why not all of Documents (My Documents).
Thank you inadvance Baz