views:

662

answers:

3

I'm working on a VB.NET program that will automatically backup my work to my FTP server. So far I am able to upload a single file, by specifying a file name using this:

     'relevant part - above is where FTP object is instantiated
       Dim _FileStream As System.IO.FileStream = _FileInfo.OpenRead()

            Try
                'Stream to which the file to be upload is written
                Dim _Stream As System.IO.Stream = _FtpWebRequest.GetRequestStream()

                'Read from the file stream 2kb at a time
                Dim contentLen As Integer = _FileStream.Read(buff, 0, buffLength)

                'Till Stream content ends
                Do While contentLen <> 0
                    ' Write Content from the file stream to the FTP Upload Stream
                    _Stream.Write(buff, 0, contentLen)
                    contentLen = _FileStream.Read(buff, 0, buffLength)
                Loop
                _Stream.Close()
                _Stream.Dispose()
                _FileStream.Close()
                _FileStream.Dispose()

                ' Close the file stream and the Request Stream


            Catch ex As Exception
                MessageBox.Show(ex.Message, "Upload Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End Try

Now I want to be able to iterate through a directory (Which contains subdirectories) and recursively call the function above. I'm having a problem getting a hold of the files in the directory.

My Question is, How can I loop through and send each file to the upload function above? Can I just send the filename to an array, or is there some sort of system object to handle this (e.g. System.IO.Directory)

Pseudocode for what I'm trying to do

                For Each Sub_directory In Source_directory

                     For Each File in Directory
                       'call the above code to transfer the file
                     Next

                'start next subdirectory
                Next

I'm trying to replicate the entire directory structure with sub directories intact. My first attempt dumped ALL files into one directory.

A: 

Have a look at the DirectoryInfo class.

klausbyskov
+2  A: 

You could go through each directory and file using recursion like this:

Public Shared Sub ForEachFileAndFolder(ByVal sourceFolder As String, _
                                       ByVal directoryCallBack As Action(Of DirectoryInfo), _
                                       ByVal fileCallBack As Action(Of FileInfo))

    If Directory.Exists(sourceFolder) Then
        Try
            For Each foldername As String In Directory.GetDirectories(sourceFolder)
                If directoryCallBack IsNot Nothing Then
                    directoryCallBack.Invoke(New DirectoryInfo(foldername))
                End If

                ForEachFileAndFolder(foldername, directoryCallBack, fileCallBack)
            Next
        Catch ex As UnauthorizedAccessException
            Trace.TraceWarning(ex.Message)
        End Try

        If fileCallBack IsNot Nothing
            For Each filename As String In Directory.GetFiles(sourceFolder)
                fileCallBack.Invoke(New FileInfo(filename))
            Next
        End If
    End If
End Sub

Edit: Usage of the Delegates:

ForEachFileAndFolder("yourPath", AddressOf dirAction, Addressof fileAction)

Public Sub dirAction(Byval dirInfo As DirectoryInfo)
    ' do something here '
End Sub

Same for the FileAction.

Bobby
Thanks Bobby, this appears to be what I'm looking for. However, I've never used "As Action" as an argument. In the initial call to ForEachFileAndFolder, what would I pass as the directoryCallBack and fielCallBack? Should these arguments be the functions I want to run on each object? e.g. the FTP transfer function = fileCallBack?
cinqoTimo
@cinqoTimo: Added an example on how to sue the delegates. Also added a check in the function for Nothing, maybe you don't wanna do something with the folders, then you can pass in Nothing.
Bobby
You are the man, it works... So a delegate is basically a private function. I had a general idea, by I don't have an OOP background - mainly HTML/CSS/PHP. Thanks for your time.
cinqoTimo
@cinqoTimo: Technically, a Delegate is nothing more than a placeholder for a sub or function. You can pass in whatever matches the specified signature. F.e. you can't see that that good in VB.NET, but in C# and the other languages Events are nothing more than a collection of Delegates which get called.
Bobby
+1  A: 

You'll have to handle directories and files separatly, but it's still pretty simple.

System.IO.DirectoryInfo constains the list files and sub-directories within a specified directory. Look for the property directories and files.

What you will want to do is specify a function that will read through all files first and then directories within the DirectoryInfo. For the files, you do what you want to do with it (Upload I think), and once you hit the Directories, call your function recursivly using the sub directory as the argument. This will go thourh all sub-directories and file.

Pseudo-Code (I call it pseudo-code cos' I don't know the exact syntax)


Sub UploadDirectory(oDirInfo as DirectoryInfo)

   For eaco oFile as FileInfo in oDirINfo.Files
     'Do your thing
   Next

   For each oDir as DirectoryInfo as oDirInfo.Directories
     ' Do some stuff if you need to separate directories
     UploadDirectory(odir)
End sub

Hope that helps.

David Brunelle