Is there a way to combine these two statements into one? - vb.net

I was wondering if there is any way in VB.NET where you can use logical operators with 1-dimensional strings.
This is part of my code, and ideally I want to be able to combine the two searches (e.g. file.GetFiles("*.mp4" And "*.wmv")):
For Each f In file.GetFiles("*.mp4")
FileBrowser.Items.Add(f.Name, 5)
i = FileBrowser.FindItemWithText(f.Name).Index
FileBrowser.Items.Item(i).Text = f.Name.Remove(f.Name.Count - f.Extension.Count, f.Extension.Count)
FileBrowser.Items.Item(i).Name = f.FullName
Next
For Each f In file.GetFiles("*.wmv")
FileBrowser.Items.Add(f.Name, 5)
i = FileBrowser.FindItemWithText(f.Name).Index
FileBrowser.Items.Item(i).Text = f.Name.Remove(f.Name.Count - f.Extension.Count, f.Extension.Count)
FileBrowser.Items.Item(i).Name = f.FullName
Next
Can it be done by using a string array or list?

If you put each file extension in an array you can just iterate through it for each extension, and the only thing you'd have to change when adding or deleting extensions is the array itself.
Dim LookForExts() As String = New String() {"*.mp4", "*.wmv", "*.mp3", "*.wav"} 'Add or remove file extensions here.
For Each ext In LookForExts
For Each f In file.GetFiles(ext)
FileBrowser.Items.Add(f.Name, 5)
i = FileBrowser.FindItemWithText(f.Name).Index
FileBrowser.Items.Item(i).Text = f.Name.Remove(f.Name.Count - f.Extension.Count, f.Extension.Count)
FileBrowser.Items.Item(i).Name = f.FullName
Next
Next

For .NET 4.0 and later,
Dim files = Directory.EnumerateFiles("C:\path", "*.*", SearchOption.AllDirectories)
.Where(Function(s) s.EndsWith(".mp4", StringComparison.OrdinalIgnoreCase)
OrElse s.EndsWith(".wmv", StringComparison.OrdinalIgnoreCase))
For earlier versions of .NET,
Dim files = Directory.GetFiles("C:\path", "*.*", SearchOption.AllDirectories)
.Where(Function(s) s.EndsWith(".mp4", StringComparison.OrdinalIgnoreCase)
OrElse s.EndsWith(".wmv", StringComparison.OrdinalIgnoreCase))
Note that 'Directory.EnumerateFiles()' is preferred over 'Directory.GetFiles()' due to performance improvements. Directory.GetFiles() method will work perfectly fine if your directory does not have a huge amount of files within.

You may consume regex in combination with Directory.EnumerateFiles. Try like this:
Regex re = new Regex("\.(mp4|wmv)$");
Dim filteredFiles = Directory.EnumerateFiles(directoryPath, "*.*", SearchOption.AllDirectories).Where(Function(c) re.IsMatch(c))

Related

Best way to loop through a list within a sub-loop

First things first, I did a search before posting this question but the answers are so generic that I could not find anything similar to what I'm trying to do. I apologize in advance if this has been answered before and I did not find it.
I have a scenario where I already collected a large list of rows (>10K) from the SQL server and put into an array (List) of strings. These rows are consisted of filenames. Because I already put them on a list, I don't want to query the SQL server again and instead want work with what I already have in memory.
This is the code I'm trying to get right:
'Valid file types for InfoLink1, InfoLink2, InfoLink3
Dim lstValidImageFormats As New List(Of String)({".JPG", ".JPEG", ".JPE", ".BMP", ".PNG", ".TIF", ".TIFF", ".GIF"})
Dim lstValidSTLFormats As New List(Of String)({".STL"})
Dim lstValidSTEPFormats As New List(Of String)({".STP", ".STEP"})
'////////////////
'// Components //
'////////////////
'We don't check Parts.InfoLink because all formats are allowed in this field
'Parts.InfoLink1 - File in Infolink1 columns MUST BE images
For i = 0 To arrStrComponentsInfolink1Values.Count - 1 'We have 10K rows with filenames in this list
For Each FileExtension As String In lstValidImageFormats
If arrStrComponentsInfolink1Values.Item(i).EndsWith(FileExtension) = False Then
End If
Next
Next
I'm trying to parse each item (filename) I have in the array arrStrComponentsInfolink1Values and check if the filename DOES NOT end with one of the extensions in the list lstValidImageFormats. If it doesn't, then I'll send the filename to another list (array).
My difficulty here is about how to iterate through each item in arrStrComponentsInfolink1Values, then check if each filename ends with one of the extensions declared in lstValidImageFormats, do what I want to do with the item if it DOES NOT end with one of those extensions, and then proceed to parse the next item in arrStrComponentsInfolink1Values.
I sincerely don't know what's the best way/performance efficient to do that.
My code above is empty because algorithmically I don't know the best approach to do what I want without querying the SQL server again with something like AND filename NOT LIKE '%.JPG' AND filename NOT LIKE '%.JPEG' AND filename NOT LIKE '%.JPE' AND filename NOT LIKE '%.BMP'...
Because I already have the data in the memory in a list, performance would be much better if I could use what I already have.
Any suggestions or material I could read to learn how to do what I'm looking for?
Thank you!
Here's how I would tackle this:
Dim invalidFormatFiles = _
From x In arrStrComponentsInfolink1Values _
Let fi = New FileInfo(x) _
Where Not lstValidImageFormats.Contains(fi.Extension.ToUpperInvariant()) _
Select x
For Each invalidFormatFile In invalidFormatFiles
' Do your processing
Next
I ended up doing this and it worked:
Dim lstValidImageFormats As New List(Of String)({".JPG", ".JPEG", ".JPE", ".BMP", ".PNG", ".TIF", ".TIFF", ".GIF"})
Dim lstValidSTLFormats As New List(Of String)({".STL"})
Dim lstValidSTEPFormats As New List(Of String)({".STP", ".STEP"})
'////////////////
'// Components //
'////////////////
'We don't check Parts.InfoLink because all formats are allowed in this field
'Parts.InfoLink1 - File in Infolink1 columns MUST BE images
Dim intExtCounter As Integer = 0
For i = 0 To arrIntComponentsInfolink1UNRs.Count - 1 'We have 10K rows with filenames in this list
intExtCounter = 0
For j = 0 To lstValidImageFormats.Count - 1
If arrStrComponentsInfolink1Values.Item(i).EndsWith(lstValidImageFormats.Item(j)) = True Then
intExtCounter += 1
End If
Next
If intExtCounter = 0 Then 'At least one file extension was found
arrIntComponentsInfolink1UNRsReportSectionInvalidExtensions.Add(i) 'File extension is not in the list of allowed extensions
End If
Next
But #41686d6564 answer was the best solution:
Dim newList = arrStrComponentsInfolink1Values.Where(Function(x) Not lstValidImageFormats.Contains(IO.Path.GetExtension(x))).ToList()
Thank you!

Filter Files and Order By Modify Date VB

I'm filtering files by multiple extensions and i want to order by files date.
I'm trying
GetFiles().OrderByDescending(Function(p) p.LastWriteTime)
but cant order like this.
Dim driver As DriveInfo = DriveInfo.GetDrives().Where(Function(x) x.DriveType = DriveType.Removable).FirstOrDefault
If driver IsNot Nothing AndAlso driver.IsReady Then
UsbRootPath = Path.GetPathRoot(driver.RootDirectory.ToString)
Dim ext = {".png", ".jpg", "*.zip"}
Dim rootFiles() As String = ext.SelectMany(Function(f) Directory.GetFiles(driver.RootDirectory.ToString, f, SearchOption.TopDirectoryOnly)).ToArray()
End If
I'm trying GetFiles().OrderByDescending(Function(p) p.LastWriteTime)
Well, that doesn't work because you use it in a SelectMany, so in kind of a sub-query. You need to apply the ordering last. Also, p is a String, the path, you need File.GetLastWriteTime:
Dim rootFiles() As String = ext.
SelectMany(Function(f) Directory.EnumerateFiles(driver.RootDirectory.ToString, f, SearchOption.TopDirectoryOnly)).
OrderByDescending(Function(f) File.GetLastWriteTime(f)).
ToArray()
I would suggest that you use the DirectoryInfo and FileInfo classes:
Dim fileInfos = extensions.SelectMany(Function(ext) New DirectoryInfo(driver.RootDirectory.FullName).
GetFiles("*" & ext)).
OrderBy(Function(fi) fi.LastWriteTime)
Exactly what you do from there depends on exactly what you want. If you want the full path of each file in an array:
Dim filePaths = fileInfos.Select(Function(fi) fi.FullName).ToArray()

Exclude files from Directory.EnumerateFiles based on multiple criteria

Is there a way to exclude files from Directory.EnumerateFiles based on multiple criteria?
The filtering based on extension works fine. But I also want to filter out any filenames which contain any of the exclusion strings. I'm not sure how to do it. I know I could iterate thru the fileArray and check each filename, but that would probably be a performance hit...I'm guessing, right?
This is example code which only uses the first exclusion thumb as a filter. Now I need to use all elements of the exclusion string array. Also, the string used in exclusion is dynamic, it won't necessarily have just the 3 filter criteria. This is just an example.
Dim ext() As String = Split(".jpg;.gif;.bmp;.tif;.png;.tiff;.jpeg", ";")
Dim exclusion() As String = Split("thumb,nothing,empty", ",")
Dim fileArray = From chkFile In Directory.EnumerateFiles(fpath, "*.*", SearchOption.TopDirectoryOnly)
Where ext.Contains(Path.GetExtension(chkFile).ToLower(System.Globalization.CultureInfo.InvariantCulture)) _
And Not Path.GetFileNameWithoutExtension(chkFile).ToLower(System.Globalization.CultureInfo.InvariantCulture).Contains(exclusion(0).Trim.ToLower)
Here's one way that uses FileInfo objects instead of strings. This eliminates all those Path calls, but should be easy to change if desired.
Dim ext() As String = {".jpg", ".gif", ".bmp", ".tif", ".png", ".tiff", ".jpeg"}
Dim exclusion() As String = {"thumb", "nothing", "empty"}
Dim fileArray = From chkFile As FileInfo In New DirectoryInfo(fpath).EnumerateFiles("*.*", SearchOption.TopDirectoryOnly)
Where ext.Contains(chkFile.Extension.ToLower(System.Globalization.CultureInfo.InvariantCulture)) _
And Not exclusion.Any(Function(x) chkFile.Name.ToLower(System.Globalization.CultureInfo.InvariantCulture).Contains(x))
Select chkFile

Extract whole row/line using Lumenworks CSV Parser

How do I read the whole row while using LumenWorks CVS parser? So far am only able to read entry by entry but not the whole row. i.e. if a row is a,b,c,d,e,f, am able to pluck out each individual alphabet. However, I want to be able to read the whole row
Currently I have:
my_csv = New CsvReader(New StreamReader(file_path), False, ",", resetPoint)
field_count = my_csv.FieldCount
While my_csv.ReadNextRecord()
'process the data here
'This code will process each individual alphabet in one row
The above reads each individual alphabet. What I want is to have something like
row = my_csv.row
Is this option available or something similar?
'EDITED'
When you have basic VB programming skills like me, this is what you come up with to solve the problem
Dim my_string As String = ""
For x As Integer = 0 To my_csv.FieldCount - 1
my_string += my_csv(x).ToString.Trim + ","
Next
my_string = Mid(my_string, 1, Len(my_string) - 1)
Return my_string
By all means use the code in the marked answer. Its super elegant!
I haven't found anything available, but this should work:
VB:
Dim rowFields = Enumerable.Range(0, my_csv.FieldCount).
Select(Function(field) my_csv(CInt(my_csv.CurrentRecordIndex), field))
Dim line As String = String.Join(my_csv.Delimiter.ToString(), rowFields)
C#:
var rowFields = Enumerable.Range(0, my_csv.FieldCount)
.Select(field => my_csv[(int)my_csv.CurrentRecordIndex, field]);
string line = string.Join(my_csv.Delimiter.ToString(), rowFields);
I found a method using the CopyCurrentRecordTo(array) method, which seems to be marginally faster (a few seconds) the wider (more columns) a file is:
C#:
string[] currentRow = new string[csv.FieldCount];
while (csv.ReadNextRecord())
{
csv.CopyCurrentRecordTo(currentRow);
var line = string.Join(csv.Delimiter.ToString(), currentRow);
}
VB (this is from Telerik converter, beware):
Dim currentRow As String() = New String(csv.FieldCount - 1) {}
While csv.ReadNextRecord()
csv.CopyCurrentRecordTo(currentRow)
Dim line = String.Join(csv.Delimiter.ToString(), currentRow)
End While

Delete multiple files

I'm trying to delete multiple files in same folder with vb.net, but I haven't succeed yet. Help please?
I tried
Dim FileToDelete1 As String
Dim FileToDelete2 As String
Dim FileToDelete3 As String
Dim FileToDelete4 As String
Dim FileToDelete5 As String
FileToDelete1 = Application.StartupPath & "\1.exe"
FileToDelete2 = Application.StartupPath & "\2.dll"
FileToDelete3 = Application.StartupPath & "\3.dll"
FileToDelete4 = Application.StartupPath & "\4.dll"
FileToDelete5 = Application.StartupPath & "\5.dll"
If System.IO.File.Exists( FileToDelete1 ) = True Then
My.Computer.FileSystem.DeleteFile( FileToDelete1 )
ElseIf System.IO.File.Exists( FileToDelete2 ) = True Then
My.Computer.FileSystem.DeleteFile( FileToDelete2 )
ElseIf System.IO.File.Exists( FileToDelete3 ) = True Then
My.Computer.FileSystem.DeleteFile( FileToDelete3 )
ElseIf System.IO.File.Exists( FileToDelete4 ) = True Then
My.Computer.FileSystem.DeleteFile( FileToDelete4 )
ElseIf System.IO.File.Exists( FileToDelete5 ) = True Then
My.Computer.FileSystem.DeleteFile( FileToDelete5 )
End If
Several problems here.
First, File.Exists returns a Boolean value.
The "=True" is unnecessary because you're basically asking if True=True. Fortunately, it is.
Second, file existence or not it's not the only way to fail. For instance, if the file is in use, you'll get an exception. You should handle it.
Third, what if you need to delete a thousand files? Would you create a String for each one of them? There are better options, for instance, the GetFiles method which will return a ReadOnly List of Strings, each one representing one file.
I don't know your needs, but to catch the files you mention, the following call can be made:
FileIO.FileSystem.GetFiles(Application.StartupPath, FileIO.SearchOption.SearchTopLevelOnly, {"?.exe", "?.dll"})
It will get every EXE and DLL file if it's name consists in only one character.
Finally, notice that if the first condition is met, no other will be evaluated, hence no other file will be deleted.
With that implementation you'll need to run the program 5 times in order to delete every file.
GetFiles method solves this as well.
Additionally, consider importing namespaces so you don't need to prefix them in every method call.
Looks like you want to do some thing like this
Dim fileNames() as string={"1","2","3"}
Dim fileTypes() as string={"exe","dll"}
directory.SetCurrentDirectory(Application.StartupPath)
For each fileName as string in fileNames
For each fileType as string in fileTypes
if My.Computer.FileSystem .FileExists (fileName &"."& fileType) then
try
My.Computer.FileSystem.DeleteFile( fileName &"."& fileType )
catch ex As Exception
'**** processings related with exception.
end try
endif
'Dim files() As String = Directory.GetFiles(dirPath, fileName &"." & fileType, SearchOption.AllDirectories)
'For Each FileToDelete as string in files
' My.Computer.FileSystem.DeleteFile( FileToDelete )
'Next
Next
Next