Copying a list of modified files from multiple source directories to equivalent destination directory - vb.net

I am learning VB.NET and writing a utility to copy only the modified files from a preset selection of folders to their equivalent in a backup directory.
For example: D:\Profiles\Mail to E:\Backup\Profiles\Mail
I can already do the copy simply with the following:
For Each item In MAILp
My.Computer.FileSystem.CopyDirectory(MAILp, MAILd, True)
Next
But the idea is count the amount of modified files to be copied, and display this all through a progress bar and the background worker (eventually)
At the moment i am working with this;
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Contants for whole activity
Dim lstFiles As New List(Of FileInfo)
Dim fsInfo As FileSystemInfo
'Constants for dirInfo's
Dim dirInfoMAILp As New DirectoryInfo(MAILp)
Dim dirInfoDESKTOPp As New DirectoryInfo(DESKTOPp)
'Loop for Mail
For Each fsInfo In dirInfoMAILp.GetFileSystemInfos
Dim strDestFileName As String = Path.Combine(MAILd, fsInfo.Name)
Dim destFileInfo As New FileInfo(strDestFileName)
If fsInfo.LastWriteTime > destFileInfo.LastWriteTime Then
lstFiles.Add(fsInfo)
End If
Next
'Loop for Desktop
For Each fsInfo In dirInfoDESKTOPp.GetFileSystemInfos
Dim strDestFileName As String = Path.Combine(DESKTOPd, fsInfo.Name)
Dim destFileInfo As New FileInfo(strDestFileName)
If fsInfo.LastWriteTime > destFileInfo.LastWriteTime Then
lstFiles.Add(fsInfo)
End If
Next
'Number of files to copy
Label1.Text = lstFiles.Count
For Each file As FileInfo In lstFiles
System.IO.File.Copy(file.FullName, DESTINATIONMAIN + file.Name, True)
Next
End Sub
My problem is in three parts:
1. If the files do not already exist in the destination, it will throw and exception. This is not good if the utility is being used for the first time. How can I use an ELSE in the loop to copy the file if it doesn't exist in the destination?
2. The copy does not copy folders, only files, can I expand it to include folders? Ideally the differential check loop targets the Top folder then goes through every sub folder and file, adding it to the list.
3. When copied to the destination folder, the files are copied to the destination top folder "E:\Backup\Profiles", rather than in the sub-folders they were copied from.
Can anyone point me in the right direction?

Related

Iterate through a directory to get subfolders and certain files

I am working on a program that will move files to a database, text files to be exact. The user will have a starting directory and inside will multiple sub folders and files and so on. I want to go through each Folder and sub folder looking for the text files and add them accordingly to the database so it resembles a directory structure in a way. In the program the files are organized such as the folders are "Categories" that are displayed into a tree view.I am only adding the folder names(as Categories) that do contain text files and their subs and so forth. As well I need to figure out where to plug in the adding of the "Category". As of right now I am using a couple of listboxes for my output until I can get it all figured out.
lstfiles.Items.Add(Dir)
For Each file In System.IO.Directory.GetFiles(Dir)
Dim fi As System.IO.FileInfo = New IO.FileInfo(file)
If fi.Extension = ".txt" Then
If lstRootFolderFiles.Items.Contains(file) = False Then
lstfiles.Items.Add(file)
AddFile(file, Gennumber(9999))
End If
End If
Next
For Each folder In System.IO.Directory.GetDirectories(Dir)
lstfiles.Items.Add(folder)
For Each file In System.IO.Directory.GetFiles(folder)
Dim fi As System.IO.FileInfo = New IO.FileInfo(file)
If fi.Extension = ".txt" Then
If lstRootFolderFiles.Items.Contains(file) = False Then
lstfiles.Items.Add(file)
End If
End If
Next
Next
I have gotten so far as to iterate through the directory and get files but it returns folders that are empty. And I need to figure out where I need to put in my addcategory function. And also remember the last one that was added so they can be added as a subcategory.
I think I am making a big mess of it all, or over thinking the whole thing.
Any assistance or guidance would be appreciated.Thank you
The end result that I came up with was much different from my original posting, as it was my way of thinking of how it was going to work. I split up the two main functions. Retrieving the Folders and retrieving the files.
DirEx is the Import Directory, CatID is the Tag of the selected Treenode where the folders are going to added in.
Private Sub DirImport_GetSubDirectories(ByVal DirEx As String, ByVal CatID As Integer)
Try
Dim ClsData As New clsNoteData
'Set the DatabaseFile Property of the class
ClsData.Database = LoadedLibraryDatabase
' Get all subdirectories
Dim subdirectoryEntries() As String = Directory.GetDirectories(DirEx)
' Loop through them to see if they have any other subdirectories
Dim subdirectory As String
For Each subdirectory In subdirectoryEntries
'If the Directory is not Empty
If Not Directory.GetFileSystemEntries(subdirectory).Length = 0 Then
Dim di As DirectoryInfo = New DirectoryInfo(subdirectory)
'Creating Random Number
Dim NewCatID As Integer = GenNumber(9999)
'Call for a new Sub Category
ClsData.NewSubCategoryNode(LoadedLibraryDatabase, NewCatID, CatID, di.Name, -1)
'Get files in the current Directory
DirImport_GetFiles(subdirectory, NewCatID)
'Get the next set of Subfolders
DirImport_GetSubDirectories(subdirectory, NewCatID)
End If
Next
Catch ex As Exception
End Try
End Sub
Private Sub DirImport_GetFiles(ByVal DirEx As String, ByVal CatID As Integer)
Dim Files() As String = Directory.GetFiles(DirEx, "*.txt")
Dim file As String
For Each file In Files
Dim clsNoteData As New clsNoteData
Dim fi As FileInfo = New FileInfo(file)
clsNoteData.Database = LoadedLibraryDatabase
clsNoteData.NewNote_ID = GenNumber(99999)
clsNoteData.NewNote_CatID = CatID
clsNoteData.NewNote_Title = Path.GetFileNameWithoutExtension(file)
clsNoteData.NewNote(False, file)
Next
End sub
So here it is for anyone who may want to do something similar.

How to compress multiple files and split the zip while compressing

Hello so I have searched for this a long time allready and havent found anything about this. I search all the folders in the given folder and create an entry in the ziparchive for each file. It is needed that i keep the fodler structure. This is what i have come up with for now.
Imports System.IO
Imports System.IO.Compression
'a list of folders I want to zip. These are all located in the testfolder.
Public Shared ListofBackupFolders As New List(Of String) From {"SDK", "Programms", "Application", "Office", "Reports", "UserSettings", "de", "Intrastat", "XSD"}
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim d As New DirectoryInfo("c:\temp\testfolder")
Dim directories = d.GetDirectories("*")
File.Create("C:\temp\test.zip").Close()
For Each directory In directories
'Only searches the Folders I selecten in the list
If ListofBackupFolders.Contains(directory.Name) Then
SearchFolder(directory.FullName)
End If
Next
End Sub
Private Sub SearchFolder(path As String)
Dim dirInfo As New DirectoryInfo(path)
Dim subDirectories = dirInfo.GetDirectories("*")
If path.EndsWith("Application") Then
'>>> Some of the selected folders are in the Application folder
For Each subdirectory In subDirectories
If ListofBackupFolders.Contains(subdirectory.Name) Then
'recursion to get all the folders in the selected folder
SearchFolder(subdirectory.FullName)
End If
Next
Else
If subDirectories.Any Then
For Each subdirectory In subDirectories
'>>> recursion to get all the folders in the selected folder
SearchFolder(subdirectory.FullName)
Next
End If
End If
Dim files = dirInfo.GetFiles("*")
Using zipToOpen As FileStream = New FileStream("C:\temp\test.zip", FileMode.Open)
Using archive As ZipArchive = New ZipArchive(zipToOpen, ZipArchiveMode.Update)
Dim readmeEntry As ZipArchiveEntry
For Each file In files
'for every File in the folders it creates the path in the zip
Dim zipPath = file.FullName.Replace("C:\", "").Replace("\", "/")
readmeEntry = archive.CreateEntryFromFile(file.FullName, zipPath, CompressionLevel.Fastest)
Next
If Not subDirectories.Any AndAlso Not files.Any Then
'if there are no files in a folder i still want the folder in the zip
Dim folderPath = path.Replace("C:\", "").Replace("\", "/") & "/"
readmeEntry = archive.CreateEntry(folderPath)
End If
End Using
End Using
End Sub
Now the problem I have is that i havent found a way to split the zip after a given volume (example 200mb).
And a other thing I need is that i have a single file that is for example 2gb i have to split that one aswell. This is seperate from the other code.

Issue using elements in a list in FOR EACH loop

I am new to VB.net and want to write an application to read a text file with a list of paths, count the number of files in all the paths, copy the everything in the path and show the progress via a progress bar with an eta of completion.
So far I have only the text file being read and the counter working correctly, but cannot work out how to use the paths already stored in pathlist list to be the sources in the copy. Here is what I have;
Public Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If System.IO.File.Exists(Application.StartupPath + "\CONFIG.txt") = True Then
Dim pathlist As New List(Of String)
' Open config.txt with the Using statement.
Using r As StreamReader = New StreamReader(Application.StartupPath + "\CONFIG.txt")
' Store contents in this String.
Dim line As String
' Read first line.
line = r.ReadLine
' Loop over each line in file, While list is Not Nothing.
Do While (Not line Is Nothing)
' Add this line to list.
pathlist.Add(line)
'count the files in the directories as we go through the loop
counter = System.IO.Directory.GetFiles(line, "*.*", SearchOption.AllDirectories).Count()
'add # of files to overall count
filecount += counter
' Read the next line.
line = r.ReadLine
Loop
End Using
Else
MessageBox.Show("Config.txt does not exist")
End If
'Label Showing total files
Label1.Text = filecount
End Sub
How would I use the line strings in pathlist to do the following:
Copy the folder with all subfile and directories to the destination folder
Update a counter so I can use a progress bar
Do an time remaining counter, how can this be estimated? Should I be calculating the size in MB's of all the data? Or something similar?
If anyone can assist or link me an example I could use, that would be great!

How to Access a txt file in a Folder created inside a VB project

I'm creating a VB project for Quiz App (in VS 2013). So I have some preset questions which are inside the project (I have created a folder inside my project and added a text file).
My question is how can I read and write contents to that file? Or if not is there any way to copy that txt file to Documents/MyAppname when installing the app so that I can edit it from that location?
In the example below I am focusing on accessing files one folder under the executable folder, not in another folder else wheres. Files are read if they exists and then depending on the first character on each line upper or lower case the line then save data back to the same file. Of course there are many ways to work with files, this is but one.
The following, created in the project folder in Solution Explorer a folder named Files, add to text files, textfile1.txt and textfile2.txt. Place several non empty lines in each with each line starting with a character. Each textfile, set in properties under solution explorer Copy to Output Directory to "Copy if newer".
Hopefully this is in tune with what you want. It may or may not work as expected via ClickOnce as I don't use ClickOnce to validate this.
In a form, one button with the following code.
Public Class Form1
Private TextFilePath As String =
IO.Path.Combine(
AppDomain.CurrentDomain.BaseDirectory, "Files")
Private TextFiles As New List(Of String) From
{
"TextFile1.txt",
"TextFile2.txt",
"TextFile3.txt"
}
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim FileName As String = ""
' loop thru each file
For Each fileBaseName As String In TextFiles
FileName = IO.Path.Combine(TextFilePath, fileBaseName)
' only access file if it exist currently
If IO.File.Exists(FileName) Then
' read file into string array
Dim contents As String() = IO.File.ReadAllLines(FileName)
' upper or lower case line based on first char.
' this means you can flip flop on each click on the button
For x As Integer = 0 To contents.Count - 1
If Char.IsUpper(CChar(contents(x))) Then
contents(x) = contents(x).ToLower
Else
contents(x) = contents(x).ToUpper
End If
Next
' save changes, being pesstimistic so we use a try-catch
Try
IO.File.WriteAllLines(FileName, contents)
Catch ex As Exception
Console.WriteLine("Attempted to save {0} failed. Error: {1}",
FileName,
ex.Message)
End Try
Else
Console.WriteLine("Does not exists {0}", FileName)
End If
Next
End Sub
End Class
This may help you
Dim objStreamReader As StreamReader
Dim strLine As String
'Pass the file path and the file name to the StreamReader constructor.
objStreamReader = New StreamReader("C:\Boot.ini")
'Read the first line of text.
strLine = objStreamReader.ReadLine
'Continue to read until you reach the end of the file.
Do While Not strLine Is Nothing
'Write the line to the Console window.
Console.WriteLine(strLine)
'Read the next line.
strLine = objStreamReader.ReadLine
Loop
'Close the file.
objStreamReader.Close()
Console.ReadLine()
You can also check this link.

How to remove files from a directory if they don't contain the list of specified files provided?

I'm currently doing a project where I need to search through a specific directory for files. If the files found are not the approved extension then the files must be moved to an archive folder. I need to user to be allowed to remove and add extensions so the list is not a set size and will most likely change weekly.
So far I'm able to loop through the directories and list all the files in there into a listbox. My problem comes when trying to differentiate between the approved list and the current list and I can't narrow down the files and display them in the list box.
My error is : 'An unhandled exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll' where my 'list1' variable count is 0 because no children were found even when there are matching approved data and current data.
Any help would be appreciate from stack overflow community! Thanks!!
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim list1 As List(Of String)
list1 = (From item As String In Me.ListBox1.Items Select item Where Me.ListBox1.Items.Contains(Me.lstApprovedItems.Items)).ToList()
ListBox1.Items.Add(list1(0))
End Sub
Dim fri As FileInfo
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim FileName1 As String = ""
Dim dir2 As New DirectoryInfo("D:\Administrator\Desktop\File Management System v0.2\File Management System\File Directories\File Directories\00000000.00F")
Dim dir1 As DirectoryInfo() = dir2.GetDirectories()
Dim fri2 As DirectoryInfo
For Each fri2 In dir1
FileName1 = Convert.ToString(fri2.Name)
Dim dir As New DirectoryInfo("D:\Administrator\Desktop\File Management System v0.2\File Management System\File Directories\File Directories\00000000.00F\" + FileName1)
Dim fiArr As FileInfo() = dir.GetFiles()
For Each Me.fri In fiArr
ListBox1.Items.Add(fri.Name)
Next fri
Next
End Sub
End Class
There are several ways to go about this, this way is similar to what you have.
' first get OK extension into an array (or list)
Dim Auth(lbAuthExt.Items.Count - 1) As String
lbAuthExt.Items.CopyTo(Auth, 0)
' storage for the result
' only save the Authorized ones if that is all you care about
Dim AuthList As New List(Of FileInfo)
Dim NoAuthList As New List(Of FileInfo)
Dim dir = New DirectoryInfo("C:\Temp")
For Each fi As FileInfo In dir.GetFiles
If Auth.Contains(fi.Extension) Then
AuthList.Add(fi)
Else
NoAuthList.Add(fi)
End If
Next
I am saving FileInfo because (presumably) you might display the names to the user without all the redundant path info. But your code will need the full path name for later Copy/Move ops.
' set the list as the datasource
lbResult.DataSource = AuthList
' display file name
lbResult.DisplayMember = "Name"
' return full name to code
lbResult.ValueMember = "FullName"
The code can of course simply loop on AuthList to do its job. If you need to show the results to the user first, there is no need to make 2 copies. DisplayMember is used to tell the ListBox which property value to display while retaining all the other info in the list.
Finally, a linq version which simply saves the full file name:
Dim myAuthList = (From func In Directory.EnumerateFiles("C:\Temp", "*.*",
System.IO.SearchOption.AllDirectories)
Where Auth.Contains(Path.GetExtension(func),
StringComparer.InvariantCultureIgnoreCase)).ToList