Searching By File Extensions VB.NET [duplicate] - vb.net

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 5 years ago.
Hi all i have been trying to search a specified directory and all sub directories for all files that have the specified file extension. However the inbuilt command is useless as it errors up and dies if you dont have access to a directory. So here's what i have at the moment:
Private Function dirSearch(ByVal path As String, Optional ByVal searchpattern As String = ".exe") As String()
Dim di As New DirectoryInfo(path)
Dim fi As FileInfo
Dim filelist() As String
Dim i As Integer = 0
For Each fi In di.GetFiles
If System.IO.Path.GetExtension(fi.FullName).ToLower = searchpattern Then
filelist(i) = fi.FullName
i += 1
End If
Next
Return filelist
End Function
However i get an "System.NullReferenceException: Object reference not set to an instance of an object." when i try to access the data stored inside the filelist string array.
Any idea's on what im doing wrong?

You didn't instantiate the Dim filelist() As String array. Try di.GetFiles(searchPattern)
Dim files() as FileInfo = di.GetFiles(searchPattern)
Use static method Directory.GetFiles that returns an array string
Dim files = Directory.GetFiles(Path,searchPattern,searchOption)
Demo:
Dim files() As String
files = Directory.GetFiles(path, "*.exe", SearchOption.TopDirectoryOnly)
For Each FileName As String In files
Console.WriteLine(FileName)
Next
Recursive directory traversal:
Sub Main()
Dim path = "c:\jam"
Dim fileList As New List(Of String)
GetAllAccessibleFiles(path, fileList)
'Convert List<T> to string array if you want
Dim files As String() = fileList.ToArray
For Each s As String In fileList
Console.WriteLine(s)
Next
End Sub
Sub GetAllAccessibleFiles(path As String, filelist As List(Of String))
For Each file As String In Directory.GetFiles(path, "*.*")
filelist.Add(file)
Next
For Each dir As String In Directory.GetDirectories(path)
Try
GetAllAccessibleFiles(dir, filelist)
Catch ex As Exception
End Try
Next
End Sub

Use System.IO.Directory.EnumerateFiles method and pass SearchOption.AllDirectories in to traverse the tree using a specific search pattern. Here is an example:
foreach (var e in Directory.EnumerateFiles("C:\\windows", "*.dll", SearchOption.AllDirectories))
{
Console.WriteLine(e);
}

Related

Getfile with multiple extension filter and order by file name

i am working on vb.net desktop application.now i need that files coming from directory is in with extension .txt and .sql and also need that files coming in order by folder name. in need both together how to do it?
Try
Dim s As String = Txtfolder.Text
Dim files As List(Of String) = New List(Of String)()
Try
For Each f As String In Directory.GetFiles(s, "*.*").Where(Function(f1) f1.EndsWith(".sql") OrElse f1.EndsWith(".txt")).OrderBy(Function(f) f.LastWriteTime).First()
files.Add(f)
Next
For Each d As String In Directory.GetDirectories(s)
files.AddRange(DirSearch(d))
Next
Catch excpt As System.Exception
MessageBox.Show(excpt.Message)
End Try
Private Function DirSearch(ByVal sDir As String) As List(Of String)
Dim files As List(Of String) = New List(Of String)()
Try
For Each f As String In Directory.GetFiles(sDir, "*.*").Where(Function(f1) f1.EndsWith(".sql") OrElse f1.EndsWith(".txt"))
files.Add(f)
Next
For Each d As String In Directory.GetDirectories(sDir)
files.AddRange(DirSearch(d))
Next
Catch excpt As System.Exception
MessageBox.Show(excpt.Message)
End Try
Return files
End Function
Here is an example of option 1 from my comment, i.e. get all file paths and filter yourself:
Dim folderPath = "folder path here"
Dim filePaths = Directory.GetFiles(folderPath).
Where(Function(s) {".txt", ".sql"}.Contains(Path.GetExtension(s))).
OrderBy(Function(s) Path.GetFileName(s)).
ToArray()
Here's an example of option 2, i.e. get paths by extension and combine:
Dim folderPath = "folder path here"
Dim filePaths = Directory.GetFiles(folderPath, "*.txt").
Concat(Directory.GetFiles(folderPath, "*.sql")).
OrderBy(Function(s) Path.GetFileName(s)).
ToArray()
An alternative method, which allows searching for multiple directories and filtering the results using multiple search patterns.
It returns an ordered List(Of String):
Private Function DirSearch(ByVal sDirList As String(), SearchPatter As String()) As List(Of String)
Return sDirList.SelectMany(
Function(dir) SearchPatter.SelectMany(
Function(filter)
Return Directory.GetFiles(dir, filter, SearchOption.AllDirectories)
End Function).OrderBy(Function(xDir) xDir)).ToList()
End Function
You can pass the method a list of paths and a list of extensions:
Dim SearchPaths As String() = New String() {"[Directory1]", "[Directory2]"}
Dim ItemSearchPattern As String() = New String() {"*.txt", "*.sql", "*.jpg"}
Dim DirListing As List(Of String) = DirSearch(SearchPaths, ItemSearchPattern)
Extract the content of a sigle directory with:
Dim FilesInDir As List(Of String) = DirListing.
Where(Function(entry) entry.ToUpper().
Contains("[DirectoryName]".ToUpper())).ToList()
This is a case insensitive filter. Remove (ToUpper()) for a case sensitive one.

VB.NET: GetFiles() in Specific Directory

Currently the line of code looks like this:
Dim files() As String = System.IO.Directory.GetFiles(path, filehead & ".*.*.fsi")
Dim seqfsi() As Integer
ReDim seqfsi(files.GetUpperBound(0))
Dim args() As String
Dim file As String = ""
For Each file In files
args = Split(file, ".")
If args.Length = 4 Then
seqfsi(System.Array.IndexOf(files, file)) = CInt(args(args.GetUpperBound(0) - 1))
End If
The problem is, sometimes, in my case, the path looks something like:
C:\Users\c.brummett\Downloads
and the split causes a split in the username. How can I avoid this problem but still split by periods? I'm sorry I don't how to make this more relatable.
My idea was to use a DirectoryInfo and do something like:
Dim di As DirectoryInfo
di = New DirectoryInfo(path)
Dim files() As String = di.GetFiles(filehead & ".*.*.fsi")
Edit: The problem with this second bit of code, is that it returns the error
Value of type '1-dimensional array of System.IO.FileInfo' cannot be converted to '1-> dimensional array of String' because 'System.IO.FileInfo' is not derived from 'String'.`
You can forget about getting an array of file names (you don't need that anyway) and iterate on the array of FileInfo:
Dim files() As FileInfo = New DirectoryInfo(path).GetFiles(filehead & ".*.*.fsi")
Dim seqfsi() As Integer
ReDim seqfsi(files.GetUpperBound(0))
Dim args() As String
For Each file As FileInfo In files
args = Split(file.Name, ".")
If args.Length = 4 Then
seqfsi(System.Array.IndexOf(files, file)) = CInt(args(args.GetUpperBound(0) - 1))
End If
Note AllDirectories and change in the line doing the splitting. I didn't look at your array structure stuff.
Dim files() As String = System.IO.Directory.GetFiles("C:\temp", "*.doc", IO.SearchOption.AllDirectories)
Dim seqfsi() As Integer
ReDim seqfsi(files.GetUpperBound(0))
Dim args() As String
Dim file As String = ""
For Each file In files
args = file.Substring(file.LastIndexOf("\") + 1).Split(".")
If args.Length = 4 Then
seqfsi(System.Array.IndexOf(files, file)) = CInt(args(args.GetUpperBound(0) - 1))
End If
Next file

vb.net get filename list from wildcard

I have string say "c:\debug\ *.txt"
In Debug folder there are severeal .txt files , say test1.txt test2.txt test3.txt .
How can I get from this string c:\debug\ *.txt an array of wildcard files?
a(0)=c:\debug\test1.txt
a(1)=c:\debug\test2.txt
a(2)=c:\debug\test3.txt
It is also possible that the string would be something like "C:\logs\12*\ *.log"
a(0)=C:\logs\120114\01.log
a(0)=C:\logs\120114\02.log
a(0)=C:\logs\120114\03.log
etc.
Anyone have any ideas on this?
I use the following code:
Dim Path As String = "C:\debug"
Dim Dir As New DirectoryInfo(Path)
Dim q = (From x In Dir.GetFiles("*.txt", SearchOption.AllDirectories) Select x.FullName).ToArray
You might need to
Import System.IO
Import System.Linq
Basically your key for the requirement is SearchOption.AllDirectories which iterates through sub directories as well.
This should do it for you. It'll handle wildcards in directory part and filename part
Private Function GetFiles(ByVal Path As String) As List(Of String)
Dim drivePart As String, dirPart As String, filePart As String
drivePart = Path.Substring(0, Path.IndexOf("\") + 1)
dirPart = Path.Substring(Path.IndexOf("\") + 1, Path.LastIndexOf("\") - Path.IndexOf("\") - 1)
filePart = Path.Substring(Path.LastIndexOf("\") + 1)
Dim directories As New List(Of String)
Dim files As New List(Of String)
'' Walk directory tree finding matches
'' This should handle wildcards in any part of the path
Dim currentIndex As Integer = 0
Dim directoryMatch As String() = dirPart.Split("\")
For Each directory As String In directoryMatch
WalkDirectories(drivePart, directories, directoryMatch, currentIndex)
currentIndex += 1
Next
For Each directory As String In directories
files.AddRange(System.IO.Directory.GetFiles(directory, filePart))
Next
Return files
End Function
Private Sub WalkDirectories(ByVal dirPart As String, ByVal directories As List(Of String), ByVal directoryMatch As String(), ByVal currentIndex As Integer)
If currentIndex = directoryMatch.Length Then Return
For Each d As String In System.IO.Directory.GetDirectories(dirPart, directoryMatch(currentIndex))
directories.Add(d)
WalkDirectories(System.IO.Path.Combine(dirPart, d), directories, directoryMatch, currentIndex + 1)
Next
End Sub
Edit: just noticed that it wont handle UNC paths but it should be pretty easy to modify for that if you need to
Editted again to handle multiple directory levels and wildcards at multiple levels (eg C:\debug\12*\log1*\errors*.txt
Use the GetFiles from My.Computer.System and the ReadOnlyCollection(of String) from the system.collections.objectModel import and a searchoption as desired (top or all)
sPath = "C:\debug" ' your desired path
sFile1 = "t*.txt" ' your desired search pattern with * wildcard
sFile2 = "test?.txt" ' your desired search pattern with ? wildcard
dim lstFiles as system.collections.ObjectModel.ReadOnlyCollection(of String) = My.Computer.Filesystem.GetFiles(sPath, FileIO.SearchOption.SearchTopLevelOnly, sFile1)
'lstfiles contains all the files that match your selection
'if you really need an array you can convert the list to array here
dim i as integer = 0
for each sFile as string in lstfiles
a(i)=sfile
i+=1
next
You could use the 'Like' keyword:
' For your example, call this function with root = "C:\logs" and wild = "12*\*.log"
Friend Function GetMyFiles(root As String, wild As String, Optional allowsub As Boolean = True) As List(Of String)
Dim a As New List(Of String), pattern As String
' ensure root ends with a \
If Not root.EndsWith("\") Then root &= "\"
' the extra * allows for subdirectories in between, if required
pattern = root & If(allowsub, "*", "") & wild
For Each f As String In My.Computer.FileSystem.GetFiles(root, FileIO.SearchOption.SearchAllSubDirectories)
If f Like pattern Then a.Add(f)
Next
Return a
End Function
Of course, if you hit a protected system directory, it'll fail.
This function is just to demonstrate the 'Like' keyword.
It will work if 'root' isn't a drive root (e.g. C:).
Done properly, a separate function would collect directories first, each tested for access permissions in a Try/Catch block. Here's how that looks:
Friend Function GetAllAccessibleDirs(ByRef Dir As String, Optional inclDir As Boolean = True, Optional Sort As Boolean = False) As List(Of String)
Dim D As New List(Of String), Q As New Queue(Of String), dummy As DirectoryInfo, s As String
If inclDir Then D.Add(Dir)
Q.Enqueue(Dir)
While Q.Count
For Each s In GetTopLevelDirs(Q.Dequeue)
Try
dummy = My.Computer.FileSystem.GetDirectoryInfo(s)
D.Add(s)
Q.Enqueue(s)
Catch
' Inaccessible folder
End Try
Next
End While
If Sort AndAlso D.Count Then D.Sort()
Return D
End Function
Friend Function GetTopLevelDirs(ByRef dir As String) As List(Of String)
Try
Return My.Computer.FileSystem.GetDirectories(dir, FileIO.SearchOption.SearchTopLevelOnly).ToList
Catch
Return New List(Of String)
End Try
End Function

VB.net Object Array throwing an exception

I am getting an exception when running the following code.
Public Function getSongs() As Song()
' Dim dir As New DirectoryInfo(Application.ExecutablePath)
Dim dir As New DirectoryInfo(directory)
Dim songsInDir() As Song = Nothing
Dim i As Integer = 0
For Each file As FileInfo In dir.GetFiles()
'only read ".mp3" files
If file.Extension = ".mp3" Then
songsInDir(i) = New Song(file.Name)
i = +i
End If
Next
Return songsInDir
End Function
I get an error on line:
songsInDir(i) = New Song(file.Name)
I get an uncaught exception that says:
"Object reference not set to an instance of an object."
The song object has a:
Public Sub new(By Val filename as String)
... sub that sets a variable and retrieves file info (this code works)
Any help would be appreciated!
Try using a list:
Public Function getSongs() As Song()
Dim dir As New DirectoryInfo(directory)
Dim songsInDir() As New List(of Song)
For Each file As FileInfo In dir.GetFiles()
'only read ".mp3" files
If file.Extension = ".mp3" Then
songsInDir.Add(New Song(file.Name)
End If
Next
Return songsInDir.ToArray()
End Function
Your problem is that arrays need a size when they're initialized and setting it to Nothing gives you exactly that. Give the array a size and don't set it to Nothing. Also, there's a much cleaner way to do this.
Public Function getSongs() As Song()
Dim songFiles As String() = Directory.GetFiles(directory, "*.mp3")
Dim songsInDir(songFiles.Length) As Song
Dim i As Integer = 0
For Each file As String In songFiles
songsInDir(i) = New Song(Path.GetFileName(file))
i = +i
Next
Return songsInDir
End Function
You should specify the array size
Dim i as Integer = dir.GetFiles().count or dir.FilesCount()
Dim songsInDir(i) As Song = Nothing
or you can use dynamic array
put this line inside your for loop
ReDim Preserve songsInDir(i)

Search engine in vb.net

I am building a search engine in vb.net which would have to search for a word entered by the user in 40 text files within the project directory.
It should return the results as the total number of matches (text files) and the number of times this word is in each file. Any suggestions for a start would be grateful.
Regards.
get a list of the files in the directory with something like: Directory.GetFiles(ProjectDir, "*.*"), then read each file in the list like this:
Dim sr As StreamReader = New StreamReader(fileName)
Dim line As String
Do
line = sr.ReadLine()
scan the line and count
Loop Until line Is Nothing
sr.Close()
Try this code, in a console application, not only could find a word
even you can get the results using a RegEx Expression.
Class TextFileInfo
Public File As System.IO.FileInfo
public Count As Integer
public FileText As String
public ItMatch as Boolean = False
Sub New (FileFullName as String,WordPattern as String)
File = new System.IO.FileInfo(FileFullName)
Using Fs As System.IO.StreamReader(File.FullName)
FileText = Fs.ReadToEnd()'//===>Read Text
End Using
Count = _CountWords(WordPattern,FileText)
ItMatch = Count > 0
End Sub
Public Sub DisplayInfo()
System.Console.WriteLine("File Name:" + File.Name)
System.Console.WriteLine("Matched Times:" & Count)
End Sub
Private Function _CountWords(Word As String,Text As String) as Integer
Dim RegEx as System.Text.RegularExpressions.Regex(Word)
return RegEx.Matches(Text).Count'//===>Returns how many times this word match in the Text
End Fuction
End Class
Public Function SearchEngine(PatternWord As String,RootDirectory As String) List(Of TextFileInfo)
Dim MatchedFiles As New List(Of TextFileInfo)
Dim RootDir As New System.IO.DirectoryInfo(RootDirectory)
For Each iTextFile as System.IO.FileInfo In RootDir.GetFiles("*.txt")
'//===>Create a object of TextFileInfo and check if the file contains the word
Dim iMatchFile as New TextFileInfo(iTextFiles.FullName,PatternWord)
If iMatchFile.ItMatch Then
'//===>Add the object to the list if it has been matches
MatchedFiles.Add(iMatchFile)
End If
Loop
retur MatchedFiles '//===>Return the results of the files that has the matched word
End Function
Sub Main()
Dim SearchResults as List(Of TextFileInfo) = SearchEngine("JajajaWord","C:\TextFiles\")
For Each iSearch As TextFileInfo In SearchResults
iSearch.DisplayInfo()
Loop
End Sub