reading file into an array - vb.net

i have a text file with the following data:
Calculated Concentrations
30.55 73.48 298.25 27.39 40.98 11.21 99.22 33.46 73.99 12.18 30.7
50 28.4 34.33 29.55 70.48 43.09 28.54 50.78 9.68 62.03 63.18 28.4
100 23.83 68.65 10.93 ?????? 31.42 8.16 24.97 8.3 114.97 34.92 15.53
200 32.15 29.98 23.69 ?????? 23.41 33.6 92.03 32.73 13.58 58.44 94.61
400 159.98 18.05 50.94 37.12 15.25 46.75 315.22 69.98 13.58 ?????? 58.77
208.82 11.07 38.15 86.31 35.5 41.88 28.25 5.39 40.83 29.98 54.42 69.48
36.09 13.16 23.26 19.31 147.56 31.86 6.77 19.45 33.6 32.87 205.47 134.21
?????? 17.35 9.96 58.61 13.44 23.97 22.13 145.17 29.55 26.54 37.12 198.33
and i would like to load this data into an array.
how do i enable the user to open a file of his choosing in vb.net?
how do i read these values into an array in vb.net?
i would like to clarify that what person-b has suggested works very very well. specifically the fields = calculationText.split(" ") was exactly what i needed; however, my next issue is the following. the data above is actually in this format:
http://pastebin.com/d29ae565b
where the i need the first value to be 0, then 50, then 100 etc. and i need it to read columns from left to right. the problem is that the values are not reading into the array in this manner. the values are actually reading like this: 6.65, 84.22, ????, 35.15. please help!

To read a file into a String variable, in VB.NET, you can use the System.IO.File.ReadAllText() function. An example is:
Imports System.IO '// placed at the top of the file'
'// some code'
Dim calculationText As String
calculationText = File.ReadAllText("calculations.txt") '// gets all the text in the file'
Where "calculations.txt" is the file name.
To your next point - to allow the user to load a file of their choosing, you can use the OpenFileDialog type. An example:
Dim fileName As String
Dim openDlg As OpenFileDialog
openDlg = New OpenFileDialog() '// make a new dialog'
If openDlg.ShowDialog() = DialogResult.OK Then
'// the user clicked OK'
fileName = openDlg.FileName '// openDlg.FileName is where it keeps the selected name'
End If
Combining this, we get:
Imports System.IO
'// other code in the file'
Dim fileName As String
Dim openDlg As OpenFileDialog
openDlg = New OpenFileDialog() '// make a new dialog'
If openDlg.ShowDialog() = DialogResult.OK Then
'// the user clicked OK'
fileName = openDlg.FileName
End If
Dim calculationText As String
calculationText = File.ReadAllText(fileName)
Now, we need to process the input. First, we need to make a list of decimal numbers. Next, we put everything in the file that is a number in the list:
Dim numbers As List(Of Decimal)
numbers = New List(Of Decimal)() '// make a new list'
Dim fields() As String
fields = calculationText.Split(" ") '// split all the text by a space.'
For Each field As String in fields '// whats inside here gets run for every thing in fields'
Dim thisNumber As Decimal
If Decimal.TryParse(field, thisNumber) Then '// if it is a number'
numbers.Add(thisNumber) '// then put it into the list'
End If
Next
This won't include Calculated Concentrations or ????? in the list. For usable code, just combine the second and last code samples.
EDIT: In response to the comment below.
With List objects, you can index them like this:
Dim myNumber As Decimal
myNumber = numbers(1)
You do not need to use the Item property. Also, when showing it in a message box, you need to turn it into a String type first, like this:
MsgBox(myNumber.ToString())

Once you have the file coming from an OpenFileDialog control or other UI control. Here's something you could do:
Dim filePath As String = "file.txt" ''* file coming from control
Dim fileContents As String = System.IO.File.ReadAllText(filePath)
Dim contentArray() As String = fileContents.Split(" ")
Then you can iterate through the array and TryParse to a number as needed.

OpenFileDialog
Read through character by character, looking for spaces to mark the end of a number, then parse the number an add it to a List. Or if the file is always short, you could use StreamReader.ReadToEnd and String.Split.
Code to start with (auto-converted from C#):
Dim ofd = New OpenFileDialog()
ofd.Title = "Select Data File"
If ofd.ShowDialog() = DialogResult.OK Then
Dim data As New StreamReader(ofd.FileName.ToString())
While data.Read() <> " "c
End While
' Read past Calculated
While data.Read() <> " "c
End While
' Read past Concentrations
Dim concentBuilder As New StringBuilder()
Dim last As Integer
Dim concentrations As New List(Of Double)()
Do
last = data.Read()
If last = " "c OrElse last = -1 Then
Dim concentStr As String = concentBuilder.ToString()
concentBuilder.Remove(0, concentBuilder.Length)
Dim lastConcentration As Double
Dim parseSuccess As Boolean = [Double].TryParse(concentStr, lastConcentration)
If Not parseSuccess Then
Console.[Error].WriteLine("Failed to parse: {0}", concentStr)
Else
concentrations.Add(lastConcentration)
End If
Else
concentBuilder.Append(CChar(last))
End If
Loop While last <> -1
For Each d As Double In concentrations
Console.WriteLine(d)
Next
End If

Related

Select text between key words

This is a follow on question to Select block of text and merge into new document
I have a SGM document with comments added and comments in my sgm file. I need to extract the strings in between the start/stop comments so I can put them in a temporary file for modification. Right now it's selecting everything including the start/stop comments and data outside of the start/stop comments.
Dim DirFolder As String = txtDirectory.Text
Dim Directory As New IO.DirectoryInfo(DirFolder)
Dim allFiles As IO.FileInfo() = Directory.GetFiles("*.sgm")
Dim singleFile As IO.FileInfo
Dim Prefix As String
Dim newMasterFilePath As String
Dim masterFileName As String
Dim newMasterFileName As String
Dim startMark As String = "<!--#start#-->"
Dim stopMark As String = "<!--#stop#-->"
searchDir = txtDirectory.Text
Prefix = txtBxUnique.Text
For Each singleFile In allFiles
If File.Exists(singleFile.FullName) Then
Dim fileName = singleFile.FullName
Debug.Print("file name : " & fileName)
' A backup first
Dim backup As String = fileName & ".bak"
File.Copy(fileName, backup, True)
' Load lines from the source file in memory
Dim lines() As String = File.ReadAllLines(backup)
' Now re-create the source file and start writing lines inside a block
' Evaluate all the lines in the file.
' Set insideBlock to false
Dim insideBlock As Boolean = False
Using sw As StreamWriter = File.CreateText(backup)
For Each line As String In lines
If line = startMark Then
' start writing at the line below
insideBlock = True
' Evaluate if the next line is <!Stop>
ElseIf line = stopMark Then
' Stop writing
insideBlock = False
ElseIf insideBlock = True Then
' Write the current line in the block
sw.WriteLine(line)
End If
Next
End Using
End If
Next
This is the example text to test on.
<chapter id="Chapter_Overview"> <?Pub Lcl _divid="500" _parentid="0">
<title>Learning how to gather data</title>
<!--#start#-->
<section>
<title>ALTERNATE MISSION EQUIPMENT</title>
<para0 verdate="18 Jan 2019" verstatus="ver">
<title>
<applicabil applicref="xxx">
</applicabil>Three-Button Trackball Mouse</title>
<para>This is the example to grab all text between start and stop comments.
</para></para0>
</section>
<!--#stop#-->
Things to note: the start and stop comments ALWAYS fall on a new line, a document can have multiple start/stop sections
I thought maybe using a regex on this
(<section>[\w+\w]+.*?<\/section>)\R(<\?Pub _gtinsert.*>\R<pgbrk pgnum.*?>\R<\?Pub /_gtinsert>)*
Or maybe use IndexOf and LastIndexOf, but I couldn't get that working.
You can read the entire file and split it into an array using the string array of {"<!--#start#-->", "<!--#stop#-->"} to split, into this
Element 0: Text before "<!--#start#-->"
Element 1: Text between "<!--#start#-->" and "<!--#stop#-->"
Element 2: Text after "<!--#stop#-->"
and take element 1. Then write it to your backup.
Dim text = File.ReadAllText(backup).Split({startMark, stopMark}, StringSplitOptions.RemoveEmptyEntries)(1)
Using sw As StreamWriter = File.CreateText(backup)
sw.Write(text)
End Using
Edit to address comment
I did make the original code a little compact. It can be expanded out into the following, which allows you to add some validation
Dim text = File.ReadAllText(backup)
Dim split = text.Split({startMark, stopMark}, StringSplitOptions.RemoveEmptyEntries)
If split.Count() <> 3 Then Throw New Exception("File didn't contain one or more delimiters.")
text = split(1)
Using sw As StreamWriter = File.CreateText(backup)
sw.Write(text)
End Using

How to format textfiles values retrieved from a directory and displayed in datagridview in vb.net

The problem now is how would I be able to format the values being displayed in datagridview from textfiles.
I have retrieved values from looping through textfiles removed the first two strings. Now I want to add separators or change the format of the displayed value like, for example:
textfile lines: result:
01Sample - line1
022 - line2
0306212019 - line3 06/21/2019
041234567890 - line4 12,345,678.90
I have already tried this one changing the defaultcellstyle but since the values are from textfiles in a directory its not affecting the output
DataGridView1.Columns("Gross Sales").DefaultCellStyle.Format = "##,0"
Private Sub ReadTextFiles()
Dim dt As New DataTable
dt.Columns.Add("Date")
dt.Columns.Add("Gross Sales")
Dim Folder As New IO.DirectoryInfo("c:\test\")
Dim lstLines As New List(Of String)
For Each fileentries As String In Folder.GetFiles("s*", IO.SearchOption.AllDirectories).OrderByDescending(Function(x) x.Name).Select(Function(x) x.FullName)
lstLines.AddRange(File.ReadAllLines(fileentries))
Next
Dim i As Integer
Dim OuterLoopIterations As Integer = CInt(lstLines.Count / 22)
For iterations = 0 To OuterLoopIterations - 1
Dim row = dt.NewRow
For col = 0 To 21
row(col) = lstLines(i).Remove(0, 2) 'i have removed the first 2 characters of each string
i += 1
Next
dt.Rows.Add(row(2), row(5), row(12), row(13), row(14), row(15), row(7), row(8), row(11))
Next
DataGridView1.DataSource = dt
'the code i tried applying
DataGridView1.Columns("Gross Sales").DefaultCellStyle.Format = "##,0"
this is my expected result
Current datagrid view:
the result should be for date column: 06/07/2019
for the gross : 48,990.14
Edit:
I tried this one
Dim B As Double
Dim Folder As New IO.DirectoryInfo("c:\test\")
Dim lstLines As New List(Of String)
For Each fileentries As String In Folder.GetFiles("s*", IO.SearchOption.AllDirectories).OrderByDescending(Function(x) x.Name).Select(Function(x) x.FullName)
B = CDbl(Val(fileentries))
lstLines.AddRange(File.ReadAllLines(B))
Next
If you want to format something as a number then it has to be a number. That means that, for example, if you read the text "1234.5" from the file and you want to display it as 1,234.50 in your grid then you have to convert the String you read to a Double or Decimal. If you do that then the numeric format specifier you're using in the grid column will work.

Search text file for a ranged value

I want to read and write the same file with StreamReader and StreamWriter. I know that in my code I am trying to open the file twice and that is the problem. Could anyone give me another way to do this? I got confused a bit.
As for the program, I wanted to create a program where I create a text if it doesnt exist. If it exists then it compares each line with a Listbox and see if the value from the Listbox appears there. If it doesnt then it will add to the text.
Dim SR As System.IO.StreamReader
Dim SW As System.IO.StreamWriter
SR = New System.IO.StreamReader("D:\temp\" & Cerberus.TextBox1.Text & "_deleted.txt", True)
SW = New System.IO.StreamWriter("D:\temp\" & Cerberus.TextBox1.Text & "_deleted.txt", True)
Dim strLine As String
Do While SR.Peek <> -1
strLine = SR.ReadLine()
For i = 0 To Cerberus.ListBox2.Items.Count - 1
If Cerberus.ListBox2.Items.Item(i).Contains(strLine) = False Then
SW.WriteLine(Cerberus.ListBox2.Items.Item(i))
End If
Next
Loop
SR.Close()
SW.Close()
SR.Dispose()
SW.Dispose()
MsgBox("Duplicates Removed!")
If your file is not that large, consider using File.ReadAllLines and File.WriteAllLines.
Dim path = "D:\temp\" & Cerberus.TextBox1.Text & "_deleted.txt"
Dim lines = File.ReadAllLines(path) 'String() -- holds all the lines in memory
Dim linesToWrite = Cerberus.ListBox2.Items.Cast(Of String).Except(lines)
File.AppendAllLines(path, linesToWrite)
If the file is large, but you only have to write a few lines, then you can use File.ReadLines:
Dim lines = File.ReadLines(path) 'IEnumerable(Of String)\
'holds only a single line in memory at a time
'but the file remains open until the iteration is finished
Dim linesToWrite = Cerberus.ListBox2.Items.Cast(Of String).Except(lines).ToList
File.AppendAllLines(path, linesToWrite)
If there are a large number of lines to write, then use the answers from this question.

Search Through Specific Set of Lines and Output Data?

I've been struggling with this for a while now, and after extensive searching, I still have yet to find an answer.
In my Visual Basic class, I have a program where I have to get text from a text file (songs.txt), display the genres in a list box, and display corresponding songs in a combo box after a genre is displayed.
Currently, this is my code.
' Variables
Dim strFilePath As String = "E:\Advanced VB\DJPlayList\DJPlayList\songs.txt"
Dim strFileError As String = "File not found. Please try again."
Dim strFileErrorTitle As String = "File Error"
Dim objReader As IO.StreamReader
Dim intCount As Integer = 0
Dim strSongGenre(intCount) As String
Dim i As Integer = 0
' Finding the file
If IO.File.Exists(strFilePath) Then
' Opening the text file
objReader = IO.File.OpenText(strFilePath)
Do Until objReader.Peek = -1
ReDim Preserve strSongGenre(intCount)
strSongGenre(intCount) = objReader.ReadLine
cboMusicGenre.Items.Add(strSongGenre(intCount))
intCount += 1
Loop
Else
MsgBox(strFileError, , strFileErrorTitle)
Close()
End If
This adds all the information from the text file into the array and loads it to the listbox, but I'm stuck at how to output the genre's specifically and the corresponding songs with it.
The text file looks as follows:
All You Need is Love-Beatles 'Song Name
Rock 'Song Genre
4.25 'Song Time
What Hurts the Most-Rascal Flatts
Country
5.25
Touch it-Busta Rhymes
Rap
5.46
My Girl-Temptations
R&B
4.35
What you know?-T.I.
Rap
4.30
How do I specifically get the genre's and the song titles? Thank you for the help in advance
So what is actually happening is that your code is reading every line and storing them all in your ComboBox.
Probably the easiest thing to do at this level would be to create 2 extra temporary string variables and instead of reading 1 line for each iteration of the loop, read the three lines that are related to each other like this
tempName= objReader.ReadLine
strSongGenre(intCount) = objReader.ReadLine
tempDuration = objReader.ReadLine
If you don't want to use the Name and Duration of the song then do nothing with them and they'll be overwritten on the next iteration of the loop
So your final code should look like this
Do Until objReader.Peek = -1
Dim tempName,tempDuration as string
ReDim Preserve strSongGenre(intCount)
tempName= objReader.ReadLine
strSongGenre(intCount) = objReader.ReadLine
tempDuration = objReader.ReadLine
cboMusicGenre.Items.Add(strSongGenre(intCount))
intCount += 1
Loop

Keeping only certain parts of a multiline text box

net 2.0 program and in it I have a multi line text box.
For one of my operations I only need to retrieve certain parts of the txt box
for instance
I need to retrieve the following
01-11-2013 15-18-12 -
Computer: 740TMP
01-11-2013 15-18-13 -
Computer: 740TMP
The text box can have just 1 entry or 30 entry. I know I can truncate the lines but then I would still have extra lines in the final results.. Any Ideas?
Use a List(Of String) to store the result with your desired lines. Then use a loop to iterate all lines in the TextBox and take what you need.
For example:
Dim desiredLines As New List(Of String)()
Dim allLInes As String() = textBox1.Lines
Dim datePattern As String = "dd-MM-yyyy HH-mm-ss"
For i As Integer = 0 To allLInes.Length - 1
Dim line As String = allLInes(i).Trim()
Dim dt As Date
If line.Length >= datePattern.Length AndAlso _
Date.TryParseExact(line.Substring(0, datePattern.Length), datePattern, Nothing, Globalization.DateTimeStyles.None, dt) Then
desiredLines.Add(dt.ToString(datePattern))
ElseIf line.StartsWith("Computer:") Then
desiredLines.Add(line.Split("-"c)(0).TrimEnd())
End If
Next