Copy File with progress bar

candyman

Member
Joined
Feb 19, 2004
Messages
6
Im attempting to make a program that will copy files reclusively in VB.NET.
basically I have a function that calculates the total size of every file in the directory and sub directories then goes through all of them and calls the CopyFile function.
this works alright in that my progress bar actually updates while the file is being copied instead of using filenames like I had been. It just seams to be going a lot slower. Five seconds for a 156k file as opposed to bellow three.
Is there a better way?

Clint
Code:
        Private Function CopyFile(ByVal OldFile As String, ByVal NewFile As String)
            Me.FileProgressbar.Value = 0
            Dim FS As New FileStream(OldFile, FileMode.Open)
            Dim FW As New FileStream(NewFile, FileMode.CreateNew)
            Dim Buffer() As Byte
            Get the bytes from file to a byte array
            ReDim Buffer(FS.Length - 1)
            Me.FileProgressbar.Maximum = FS.Length
            FS.Read(Buffer, 0, Buffer.Length)
            Do your stuff :-)
            For i As Int32 = 0 To Buffer.Length - 1
                Me.FileProgressbar.Value += 1
                FW.WriteByte(Buffer(i))
                Me.TotalProgressbar.Value += 1
            Next
            FS.Close()
            FW.Close()
        End Function
 
Writing one byte at a time will be painfully slow. Try writing in larger blocks, 1024 is a good size -- on average that block size yields the best speed vs number of updates.
 
IngisKahn said:
Writing one byte at a time will be painfully slow. Try writing in larger blocks, 1024 is a good size -- on average that block size yields the best speed vs number of updates.
I changed it to write and update the progressbars every kb and that helped a lot.
It copied a 75.5 Meg file 1.53125 Seconds faster then File.Copy :-)
Thanks for the help.
 
I believe that streams have a buffer size. Maybe using the buffersize of the stream as the amount of data to copy at once would give the best results ;). I think default it is 4 kb (so your 1 kb is a lot better than a single byte :D ).
 
My Code with a single progressbar took 42.374 seconds to copy a 483,005 kb file, File.Copy took 46.343 seconds
two progressbars:
My Code: 68.28 Seconds
File.Copy: 37.343 Seconds

No Progressbars:
Mine: 23.796 Seconds
.NET: 41.499 Seconds

that last one surprised me.
figured that at best mine would be just as fast as File.Copy, but apparently not...

Clint
 
IngisKahn said:
That will only help if you have multi disks.
Not really, the IO thread can be blocked while the UI thread is updating the UI. If you mean that multiple threads wont help with the base IO then you are of course correct.
 
Private Function CopyFile(ByVal OldFile As String, ByVal NewFile As String)

Dim m_aBuffer(512) As Byte
Dim m_iRemotePort, m_iBytes As Int32

Me.FileProgressbar.Value = 0
Dim FS As New FileStream(OldFile, FileMode.Open)
Dim FW As New FileStream(NewFile, FileMode.Create)
Do While (True)
m_aBuffer.Clear(m_aBuffer, 0, m_aBuffer.Length)

m_iBytes = FS.Read(m_aBuffer, 0, m_aBuffer.Length)
FW.Write(m_aBuffer, 0, m_iBytes)
Me.FileProgressbar.Value += m_iBytes
If (m_iBytes <= 0) Then
Exit Do
End If
Loop

FS.Close()
FW.Close()
End Function
 
Speaking of comments... how about adding some? :p

Also, its not good practice to have your Do Loop loop forever
In that case, you could just say
Do
Loop
but, its also not good to have it exit on the Exit Do.
You should integrate the condition that exits the loop into the loop itself.
Do
Loop Until m_iBytes <= 0
 
Back
Top