VB.Net (2019) File I/O Mixed Data Help Please? - vb.net

I am old and used to older VBA in Excel and Older VB code. Now I am trying to work in Visual Studio Community with VB. I have looked for help but everything I find for .NET comes up with C++ or C# code which I don't follow. I haven't even been able to find a book to help converting to the newer format of code. I am used to;
Dim outpath as integer
Dim aString as String
Dim aDouble as Double
aString = "Some Text"
aDouble = 3.1429
outpath = FreeFile
Open "C:\afolder\somedata.dat" For Output As outpath
print #outpath, aString
print #outpath, aDouble
close #outpath
To read data I'm used to using the aString = input #outpath instructions.
From what I have read it appears I should be using IO.Stream functions but have not found anything that would replicate the old method I am used to above.
Can somebody please point me to some internet pages that cover this in VB rather than falling into C code which I cannot translate to VB.
Thank you kindly.

Sure, there are a number of ways to do this. I also came from VB6, and lots of VBA.
So, to convert your above, and to write out to a file?
Well, one apporach (and we even did this in VBA) was to create a string, concentante the values to the string, and then write the string out to a file.
It is easy, but you have to in code toss in the next line character.
So, this will work:
Dim aString As String
Dim aDouble As Double
aString = "Some Text"
aDouble = 3.1429
Dim strPath As String = "C:\test\somedata.dat"
Dim strOutBuf As String = ""
strOutBuf = aString
strOutBuf = strOutBuf & vbCrLf & aDouble
File.WriteAllText(strPath, strOutBuf)
So, for a few easy lines of text - very easy.
However, for a lot of code, and a line by line output - similar to VBA?
Then you do it this way:
Dim FILE_NAME As String = "C:\test\test2.txt"
Dim MyFileWriter As New StreamWriter(FILE_NAME)
Dim aString As String
Dim aDouble As Double
aString = "Some Text"
aDouble = 3.1429
MyFileWriter.WriteLine(aString)
MyFileWriter.WriteLine(aDouble)
For i = 1 To 10
MyFileWriter.WriteLine(i)
Next
MyFileWriter.Close()
Note that in above, the file does not (can not) already exist.
So, you have to deal with that issue.
You can either delete the file before you start writing.
eg:
Dim FILE_NAME As String = "C:\test\test2.txt"
If File.Exists(FILE_NAME) Then
File.Delete(FILE_NAME)
End If
(and then the rest of your code follows. So there no need (or concept) of FreeFile() anymore.
output:
Some Text
3.1429
1
2
3
4
5
6
7
8
9
10
Edit: --------------------------------
Well, showing how to write out a file is kind of like the hug, without the kiss. So, now, how can we read the file?
Well, it really depends on what we want to do with that input. But .net tends to work reading (or in fact writing) the whole thing in one shot.
But, a line by line read would look like this:
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim FILE_NAME As String = "C:\test\test2.txt"
Dim MyFileReader As New StreamReader(FILE_NAME)
Do While MyFileReader.EndOfStream = False
Debug.Print("one line of file = " & MyFileReader.ReadLine)
Loop
MyFileReader.Close()
End Sub
output:
one line of file = Some Text
one line of file = 3.1429
one line of file = 1
one line of file = 2
one line of file = 3
one line of file = 4
one line of file = 5
one line of file = 6
one line of file = 7
one line of file = 8
one line of file = 9
one line of file = 10

' vb.net has allowed declaration and assignment on the same line for more than 20yrs now
Dim aString as String = "Some Text"
Dim aDouble as Double = 3.1429
' New API methods do not use integers to track files.
' That was always kind of weird.
Dim outpath As String = "C:\afolder\somedata.dat"
' StreamReader/StreamWriter are great, and you should learn them,
' but you don't need them for this sample
System.IO.File.WriteAllText(outpath, $"{aString}{vbCrLf}{aDouble}")
' Interpolated strings (like above) are kind of fun, too
Again, without the comments and assuming an Imports directive for System.IO, to highlight how simple this can be:
Dim aString as String = "Some Text"
Dim aDouble as Double = 3.1429
Dim outpath As String = "C:\afolder\somedata.dat"
File.WriteAllText(outpath, $"{aString}{vbCrLf}{aDouble}")
If the interpolated string is too confusing, here's one more option:
Dim aString as String = "Some Text"
Dim aDouble as Double = 3.1429
Dim outpath As String = "C:\afolder\somedata.dat"
File.WriteAllText(outpath, aString)
File.AppendAllText(outpath, aDouble.ToString("r"))
However, that actually opens, writes, and closes the file twice. It's extra I/O, which is some of the slowest stuff you can do in a computer, so I don't recommend it.
Instead, you could build the output string with concatenation, but I'm sure you're aware that can also be cumbersome, so here's a final alternative with a System.IO.StreamWriter:
Dim aString as String = "Some Text"
Dim aDouble as Double = 3.1429
Dim outpath As String = "C:\afolder\somedata.dat"
'Using blocks (added way back in 2005) replace the need to Close the file
' Moreover, they promise to dispose of the file handle
' **even if there's an exception/error**,
' making your code safer and better.
Using writer As New StreamWriter(outpath)
writer.WriteLine(aString)
writer.WriteLine(aDouble)
End Using
Then to read the values back:
Dim filePath As String = "C:\afolder\somedata.dat"
Dim aString as String
Dim aDouble as Double
Using reader As New StreamReader(filePath)
aString = reader.ReadLine()
aDouble = Double.Parse(reader.ReadLine())
End Using

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

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.

How to read from a 2-line text file and output each line to 2 variables in vb.net

Hello in my program I need for a text file containing 2 lines to be read and each line's contents to be put into their own variable. the text file is called "account.txt" and is under the directory Documents. the code i have curently that sees if it exists is this:
If File.Exists(System.IO.Path.Combine(My.Computer.FileSystem.SpecialDirectories.MyDocuments, "Account.txt")) Then
MsgBox("Account found and is being loaded!")
End If
I would like in that if statement for the file to be read and each line to be read and contents to be put into their own variable. Any help is greatly appreciated!
You could either use a collection like String() or List(Of String) or read them with File.ReadLines or File.ReadAllLines and assign index 0 to variable 1 and index 1 to variable 2:
Dim path = Path.Combine(My.Computer.FileSystem.SpecialDirectories.MyDocuments, "Account.txt")
If File.Exists(path) Then
Dim allLines = File.ReadAllLines(path)
Dim line1 As String = allLines(0) ' indices are zero based
Dim line2 As String = allLines(1)
End If
You can also use ElementAtOrDefault(1) instead of allLines(1) if you're not sure if the file contains two lines at all. It'l be Nothing if it contains less:
Dim line2 As String = allLines.ElementAtOrDefault(1) ' can be Nothing
If File.Exists(System.IO.Path.Combine(My.Computer.FileSystem.SpecialDirectories.MyDocuments, "Account.txt")) Then
Dim accountReader As StreamReader = new StreamReader(My.Computer.FileSystem.SpecialDirectories.MyDocuments, "Account.txt")
Dim line1 As String = accountReader.ReadLine()
Dim line2 As String = accountReader.ReadLine()
reader.Close()
End If
This should work, have not tested it I usually work on C# so I tried to convert it to VB.Net I usually prefer to reader all lines into arrays and before assigned to it I do all necessary checks but this should get you started.
I seperated it like this since you mentioned that you want line contents into different variables.
Hope this helps you :)

For some reason my program is not reading the file that I asked to be read

You can see thatt I've opened the file just below, but I've recently discovered that It is reading a file open above, which I have closed.
Dim TestNO As Integer
Dim myLines As New List(Of String)
Dim sb As StringBuilder
FileOpen(10, "F:\Computing\Spelling Bee\testtests.csv", OpenMode.Input)
Dim Item() As String = Split(fullline, ",")
Dim MaxVal As Integer = Integer.MaxValue
Do Until EOF(10)
fullline = LineInput(10)
If Item(7) > MaxVal Then
MaxVal = Item(7)
TestNO = MaxVal
End If
Loop
This is where I open and close my previous file.
Dim flag As Boolean = False
FileOpen(1, "F:\Computing\Spelling Bee\stdnt&staffdtls\stdnt&staffdtls.csv",
OpenMode.Input)
Do Until EOF(1)
fullline = LineInput(1)
Dim item() As String = Split(fullline, ",")
If enteredusername = item(0) And enteredpassword = item(1) Then
Console.WriteLine()
Console.Clear()
Console.WriteLine("Welcome," & item(3) & item(4))
Threading.Thread.Sleep(1000)
Console.Clear()
flag = True
If item(2) = "p" Then
FileClose(1)
pupilmenu()
ElseIf item(2) = "s" Then
FileClose(1)
staffmenu()
ElseIf item(2) = "a" Then
FileClose(1)
adminmenu()
FileOpen, EOF, and LineInput are all old VB6-style methods which are provided primarily for backwards compatibility. It would be far preferable to use the new .NET classes provided in the System.IO namespace. For instance, this same task is easily performed line this:
For Each line As String In File.ReadAllLines("F:\Computing\Spelling Bee\stdnt&staffdtls\stdnt&staffdtls.csv")
Dim fields() As String = line.Split(","c)
If (enteredUserName = fields(0)) And (enteredPassword = fields(1)) Then
' ...
End If
Next
Notice that I also used line.Split rather than Split(line), which is also an old VB6-style method. It's better to use the new String.Split method.
The File.ReadAllLines method opens the file, reads the entire contents of the file, closes the file, and then returns all of the data as an array of strings, with each item in the array being one line from the file. This is a very simple way to read an entire file. If it is a particularly large file, however, it would be better to use a FileStream object to read one line at a time.
Also, it's worth mentioning that reading a CSV file yourself can be complicated. They aren't always as simple as simply splitting on commas. For instance, the following is an example of a valid CSV line:
Bill, "Red, White, and Blue", Smith
As you can see, that line only contains three fields, but it contains four commas. Also, the quotation marks should not be considered as part of the value in the second field. The easiest way to read a CSV file is to use the TextFieldParser class, which handles all of those eccentricities.

Search/Replace in VB.NET

Been following the threads for sometime as a novice (more of a newbie) but am now starting to do more.
I can read how to open a text file but am having trouble understanding the .replace functionality (I get the syntax just can't get it to work).
Scenario:
Inputfile name = test_in.txt
replace {inputfile} with c:\temp\test1.txt
I'm using test.txt as a template for a scripting tool and need to replace various values within to a new file called test_2.txt.
I've got variables defining the input and output files without a problem, I just can't catch the syntax for opening the new file and replacing.
You really have not given us that much to go on. But a common mistake in using String.Replace is that it makes a copy of the source which needs to be saved to another variable or else it will go into the bit bucket. So in your case, something like this should work.
Dim Buffer As String 'buffer
Dim inputFile As String = "C:\temp\test.txt" 'template file
Dim outputFile As String = "C:\temp\test_2.txt" 'output file
Using tr As TextReader = File.OpenText(inputFile)
Buffer = tr.ReadToEnd
End Using
Buffer = Buffer.Replace("templateString", "Hello World")
File.WriteAllText(outputFile, Buffer)
Try something like this:
Dim sValuesToReplace() As String = New String() {"Value1", "Value2", "Value3"}
Dim sText As String = IO.File.ReadAllText(inputFilePath)
For Each elem As String In sValuesToReplace
sText = sText.Replace(elem, sNewValue)
Next
IO.File.WriteAllText(sOutputFilePath, sText)
It depends if you want to replace all values with only one value, or with different values for each. If you need different values you can use a Dictionary:
Dim sValuesToReplace As New Dictionary(Of String, String)()
sValuesToReplace.Add("oldValue1", "newValue1")
sValuesToReplace.Add("oldValue2", "newValue2")
'etc
And then loop throgh it with:
For Each oldElem As String In sValuesToReplace.Keys
sText = sText.Replace(oldElem, sValuesToReplace(oldElem))
Next