I need to use Directory.GetFiles but with a few more conditions - vb.net

Here's an example. Lets say I have two files in a directory:
Filename_v1.pdf
Filename_v1_ABC.pdf
Here's some code:
Dim StorageRoot = "SomePath"
Dim RootName = "Filename"
Dim Suffix = "_v"
Dim matchingFiles as string()
matchingFiles = Directory.GetFiles(StorageRoot, Path.GetFileNameWithoutExtension(file.FileName.ToString) + "*.*")
This returns both files mentioned above, but I need to only match files where the first * in *.* if it is numeric. So I need it to ignore a file if it has anything other than a number after the Suffix.
---- Edit ----
It chewed some of my example. Here's some pseudo code:
matchingFiles = Directory.GetFiles(StorageRoot, Path.GetFileNameWithoutExtension(file.FileName.ToString) + "onlyifitisnumeric.*")

One possibility would be to use Regular expressions in order take only those file whose name is matching the pattern you want to have and filter the result from GetDirectory. The pattern in this case could be:
.*_v[0-9]\.pdf
meaning
.*_v <- all symbols followed by "_v"
[0-9] <- followed by a number
\.pdf <- followed by ".pdf"
The pattern can also use the \d character class that means Matches any decimal digit. and makes the pattern shorter:
.*_v\d\.pdf
And the code can look like this:
dim path = "d:\\temp\\xml\\"
dim files = Directory.GetFiles(path, "*.pdf")
Dim rx = new Regex(".*_v\d\.pdf") ' or Dim rx = new Regex(".*_v[0-9]\.pdf")
for each file in files
if rx.IsMatch(file) then
' do something with the file
Console.WriteLine(file)
end if
next file
If you want your code to be succinct then you could use LINQ to Objects:
dim path = "d:\\temp\\xml\\"
dim files = Directory.GetFiles(path, "*.*")
Dim rx = new Regex(".*\d\.pdf") ' or Dim rx = new Regex(".*[0-9]\.pdf")
dim filteredFiles = files.Where(function(file) rx.IsMatch(file))

Here is a sample:
Imports System.Text.RegularExpressions
Imports System.IO
[...]
Dim rx As New Regex("^filename_v\d$")
Dim f = (From fItem As String In IO.Directory.GetFiles("PathToFiles")
Where rx.IsMatch(IO.Path.GetFileNameWithoutExtension(fItem))
Select fItem).ToArray
' Test Output
MessageBox.Show(String.Join(vbCrLf, f))
Use Regex("^filename_v\d+$") to match numbers of any length.

Here what you can do. First Get files with _v*_*, which possible using regular wildcards. Then, apply additional pattern you need to get the subset of files.
Dim files As IEnumerable(Of String) = _
Directory.GetFiles("your path", "your initial optional wildcard").Where(Function(f) Regex.IsMatch(f, "<your pattern>"))

Related

Reading text from one file, to check other text file for matches

So I'm new to VB.NET, and I'm trying to read through 2 separate text files. File2 first & pulling a variable from it. I then want to take that variable, and check File1 to see if the string matches. Both files are relatively large, and I have to trim part of the string from the beginning, hence the multiple splits. So currently, this is what I have. But where I'm getting hung up is, how do I get it to check every line to see if it matches with the other file?
Public Function FileWriteTest()
Dim file1 = My.Computer.FileSystem.OpenTextFileReader(path)
Dim file2 = My.Computer.FileSystem.OpenTextFileReader(path)
Do Until file2.EndOfStream
Dim line = file2.ReadLine()
Dim noWhiteSpace As New String(line.Where(Function(x) Not Char.IsWhiteSpace(x)).ToArray())
Dim split1 = Split(noWhiteSpace, "=")
Dim splitStr = split1(0)
If splitStr.Contains(HowImSplittingText) Then
Dim parameter = Split(splitStr, "Module")
Dim finalParameter = parameter(1)
End If
'Here is where I'm not sure how to continue. I have trimmed the variable to where I would like to check with the other file.
'But i'm not sure how to continue from here.
Here are a couple of cleanup notes:
Get the lines of your first file by using IO.File.ReadAllLines (documentation)
Get the text of the second file by using IO.File.ReadAllText (documentation)
Use String.Replace (documentation) instead of Char.IsWhitespace, this is quicker and much more obvious as to what is going on
Use String.Split (documentation) instead of Split (because this is 2021 not 1994).
In terms of what you would do next, you would call String.IndexOf (documentation) on the second file's text, passing your variable value, to see if it returns a value greater than -1. If it does, then you know where at in the file the value exists.
Here is an example:
Dim file1() As String = IO.File.ReadAllLines("path to file 1")
Dim file2 As String = IO.File.ReadAllText("path to file 2")
For Each line In file1
Dim noWhiteSpace As String = line.Replace(" ", String.Empty)
Dim split1() As String = noWhiteSpace.Split("=")
If (splitStr.Length > 0) Then
Dim splitStr As String = split1(0)
If splitStr.Contains(HowImSplittingText) Then
Dim parameter() As String = splitStr.Split("Module")
If (parameter.Length > 0) Then
Dim finalParameter As String = parameter(0)
Dim index As Integer = file2.IndexOf(finalParameter)
If (index > -1) Then
' finalParameter is in file2
End If
End If
End If
End If
Next

VB.NET Path to file with unknown file extension (but known name)

Could anyone help me with getting file path when I know file name (which is constant and won´t change) but don´t know file extension (can change depending on users selection in Excel):
Dim MyAppPath As String = My.Application.Info.DirectoryPath
Dim ExcelfilePath As String = IO.Path.Combine(MyAppPath, "bundle\" & "Rozpis.xlsm")
Dim ExcelfileBackupPath As String = IO.Path.Combine(MyAppPath, "bundle\backup\" & "Rozpis.xlsm")
I want it to be like this - to match any file with this particular name "Rozpis":
Dim MyAppPath As String = My.Application.Info.DirectoryPath
Dim ExcelfilePath As String = IO.Path.Combine(MyAppPath, "bundle\" & "Rozpis.*")
Dim ExcelfileBackupPath As String = IO.Path.Combine(MyAppPath, "bundle\backup\" & "Rozpis.*")
(This code is part of simple "self-protecting" mechanism for my app.)
What I tried:
I looked at regex (but if there is simpler way than regex it would be better - tried filemame.* - not working) as potential option (specifically this one: /(.)+(doc|docx|pdf)$/i ) but I don´t know much how to use it. I got error Regex cannot be converted to string when tried to use like this:
// Don´t remember the code exactly - something like this:
// regex = New Regex as regex
Dim ExcelfilePath As String = IO.Path.Combine(MyAppPath, "bundle\" & "Rozpis." & regex)
Dim ExcelfileBackupPath As String = IO.Path.Combine(MyAppPath, "bundle\backup\" & "Rozpis" & regex)

Count words in an external file using delimiter of a space

I want to calculate the number of words in a text file using a delimiter of a space (" "), however I am struggling.
Dim counter = 0
Dim delim = " "
Dim fields() As String
fields = Nothing
Dim line As String
line = Input
While (SR.EndOfStream)
line = SR.ReadLine()
End While
Console.WriteLine(vbLf & "Reading File.. ")
fields = line.Split(delim.ToCharArray())
For i = 0 To fields.Length
counter = counter + 1
Next
SR.Close()
Console.WriteLine(vbLf & "The word count is {0}", counter)
I do not know how to open the file and to get the do this, very confused; would like an explanation so I can edit and understand from it.
You're going to be reading a file as the source of the data, so let's create a variable to refer to its filename:
Dim srcFile = "C:\temp\twolines.txt"
As you have shown already, a variable is needed to hold the number of words found:
Dim counter = 0
To read from the file, a StreamReader will do the job. Now, we look at the documenation for it (yes, really) and notice that it has a Dispose method. That means that we have to explicitly dispose of it after we've used it to make sure that no system resources are tied up until the computer is next rebooted (e.g there could be a "memory leak"). Fortunately, there is the Using construct to take care of that for us:
Using sr As New StreamReader(srcFile)
And now we want to iterate over the content of the file line-by-line until the end of the file:
While Not sr.EndOfStream
Then we want to read a line and find how many items separated by spaces it has:
counter += sr.ReadLine().Split({" "c}, StringSplitOptions.RemoveEmptyEntries).Length
The += operator is like saying "add n to a" instead of saying "a = a + n". The {" "c} is a literal array of the character " "c. The c tells it that is a character and not a string of one character. The StringSplitOptions.RemoveEmptyEntries means that if there was text of "one two" then it would ignore the extra spaces.
So, if you were writing a console program, it might look like:
Imports System.IO
Module Module1
Sub Main()
Dim srcFile = "C:\temp\twolines.txt"
Dim counter = 0
Using sr As New StreamReader(srcFile)
While Not sr.EndOfStream
counter += sr.ReadLine().Split({" "c}, StringSplitOptions.RemoveEmptyEntries).Length
End While
End Using
Console.WriteLine(counter)
Console.ReadLine()
End Sub
End Module
Any embellishments such as writing out what the number represents or error checking are left up to you.
With Path.Combine you don't have to worry about where the slashes or back slashes go. You can get the path of special folders easily using the Environment class. The File class of System.IO is shared so you don't have to create an instance.
Public Sub Main()
Dim p As String = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Chapters.txt")
Debug.Print(Environment.SpecialFolder.MyDocuments.ToString)
Dim count As Integer = GetCount(p)
Console.WriteLine(count)
Console.ReadKey()
End Sub
Private Function GetCount(Path As String) As Integer
Dim s = File.ReadAllText(Path)
Return s.Split().Length
End Function
Use Split function, then Directly get the length of result array and add 1 to it.

Select files from directory order of there names

I have 'N' number of files in a folder, the file names follows some common procedure(file0....fileN). the file names looks like:
file1.pdf
..
file7.pdf
..
file10.pdf
..
file15.pdf
..
fileN.pdf
Am collecting these files into a list of string using the following code:
Dim Files As String() = Directory.GetFiles(folderBase + "\files", "*.pdf")
here what is the problem am facing is that am getting in the list in the following order:
file1.pdf
file10.pdf
..
file2.pdf
..
file15.pdf
..
fileN.pdf
Getting file10.pdf after file1.pdf. i want to get file names in the sequential order(file1.pdf,file2.pdf...etc)
i have tried this also but it will not solve my problem:
Dim Files As List(Of String) = Directory.GetFiles(folderBase + "\files", "*.pdf").OrderBy(Function(f) New FileInfo(f).Name).ToList()
If you need to use an array then sort function can be used
Dim Files As String() = Directory.GetFiles(folderBase + "\files", "*.pdf")
System.Array.Sort(Of String)(Files)
Here is an approach that uses sorted dictionary. It assumes that the file names are letters followed by number(s). This works by making the file names the same length and using that as the key for the sorted dictionary.
'get the file name only
Dim fnames As IEnumerable(Of String) = From f In Files
Select IO.Path.GetFileNameWithoutExtension(f)
'get the longest file name
Dim max As Integer = fnames.Max(Function(fs) fs.Length)
'a palce for the results
Dim sd As New SortedDictionary(Of String, String)
Dim nums() As Char = "0123456789".ToCharArray
'create dictionary entries.
For ix As Integer = 0 To fnames.Count - 1
Dim fn As String = fnames(ix)
Dim idx As Integer = fn.IndexOfAny(nums)
If idx >= 0 Then fn = fn.Insert(idx, New String(" "c, max - fn.Length))
sd.Add(fn, Files(ix))
Next
Dim l As List(Of String) = sd.Values.Select(Function(f) IO.Path.GetFileName(f)).ToList
When working with paths use the methods in IO.Path, e.g.
Dim Files As String() = IO.Directory.GetFiles(IO.Path.Combine(folderBase, "files"), "*.pdf")
One other thing, use & for concatenation of strings not +.

Renaming all files in a folder

I'm wondering if it's possible to rename all the files in a folder with a simple program, using vb.NET
I'm quite green and not sure if this is even possible.
Lets say there is a folder containing the files:
Text_Space_aliens.txt, fishing_and_hunting_racoons.txt and mapple.txt.
Using a few credentials:
Dim outPut as String = "TextFile_"
Dim fileType as String = ".txt"
Dim numberOfFiles = My.Computer.FileSystem.GetFiles(LocationFolder.Text)
Dim filesTotal As Integer = CStr(numberOfFiles.Count)
Will it be possible to rename these, regardless of previous name, example:
TextFile_1.txt, TextFile_2.txt & TextFile_3.txt
in one operation?
I think this should do the trick. Use Directory.GetFiles(..) to look for specific files. Enumerate results with a for..each and move (aka rename) files to new name. You will have to adjust sourcePath and searchPattern to work for you.
Private Sub renameFilesInFolder()
Dim sourcePath As String = "e:\temp\demo"
Dim searchPattern As String = "*.txt"
Dim i As Integer = 0
For Each fileName As String In Directory.GetFiles(sourcePath, searchPattern, SearchOption.AllDirectories)
File.Move(Path.Combine(sourcePath, fileName), Path.Combine(sourcePath, "txtFile_" & i & ".txt"))
i += 1
Next
End Sub
In your title you state something about chronologically, but within your question you never mentioned it again. So I did another example ordering files by creationTime.
Private Sub renameFilesInFolderChronologically()
Dim sourcePath As String = "e:\temp\demo"
Dim searchPattern As String = "*.txt"
Dim curDir As New DirectoryInfo(sourcePath)
Dim i As Integer = 0
For Each fi As FileInfo In curDir.GetFiles(searchPattern).OrderBy(Function(num) num.CreationTime)
File.Move(fi.FullName, Path.Combine(fi.Directory.FullName, "txtFile_" & i & ".txt"))
i += 1
Next
End Sub
I've never done Lambdas in VB.net but tested my code and it worked as intended. If anything goes wrong please let me know.