vb.net - Search textfile from certain string, read from that point - vb.net

this is probably not that hard to do.
But I've got two text files. The first has got a list of certain keywords.
Each one if these keywords are fed into a combobox.
Now, when I choose one of the items from this combobox, I want to search the other textfile for the same keyword and read from that point to the next keyword. And then feed each line into a listbox. Hope I make myself understood.
Perhaps I should use an INI-file for this purpose, doesn't really matter for me.
The textfiles have this structure;
Textfile1:
London
Oslo
New York
Hamburg
Amsterdam
The second textfile has this structure;
Textfile2:
'London'
Apples
Oranges
Pears
'Oslo'
Pasta
Salami
Monkeyballs
'New York'
Dada
Duda
Dadadish
Etc etc.
Is this possible? The reason I want to do it this way is to create a fully dynamic system. One which relies fully on whatever information is stored in these textfiles. I'm gonna build pretty complex strings from these results later on.
So far, I've got this to read the first file and add each line to the combobox:
Dim oReadMenuFunction as System.IO.StreamReader
oReadMenuFunction = IO.File.OpenText("textfile1.txt")
Do While oReadMenuFunction.Peek <> -1
Dim LineIn as String = oReadMenuFunction.ReadLine()
Combobox.Items.Add(LineIn)
Loop

Here's a sample function you could use to parse your second file. It takes a keyword as argument and returns the associated items:
Function ReadData(ByRef keyword As String) As IEnumerable(Of String)
Dim result = New List(Of String)
Using reader = New StreamReader("file2.txt")
Dim line As String = reader.ReadLine()
Dim take = False
Do While line IsNot Nothing
If line.StartsWith("'") Then
take = False
End If
If String.Equals("'" + keyword + "'", line) Then
take = True
End If
If take And Not String.IsNullOrEmpty(line) And Not line.StartsWith("'") Then
result.Add(line)
End If
line = reader.ReadLine()
Loop
End Using
Return result
End Function
And you use it like this:
Dim items = ReadData("London")

Related

Saving contents of multiple text boxes and possibly combo boxes

I'm working on a basic application that lets you track experience earned across up to 3 skills. The names of the skills are in a combo box (not sure if the best) and the beginning and ending values are in text boxes.
I want to add a save button that saves the ending values and selected skills, when pressing the load button it would populate the combo boxes with saved skills and input the old ending values into the new beginning ones.
I've been working on this all day, searching for a long time I've come up with similar solutions but nothing seems to work right. I'm still a bit of a beginner so some of the solutions I don't understand. Also, this has to work for VBNet.
The closest solution I've come across is:
File.WriteAllText("C:\Data.txt", String.Join("|", new String({TextBox1.Text, TextBox2.Text, TextBox3.Text}))
I'd like the file to stay with the project in the main directory though. Would this work for combo boxes as well, and how to load the values back in?
I'm still a newbie to VB, hope this question makes sense.
If I get your idea right, please find some functions below if they can help:
One can read (or write) text:
This one can populate the needed string to 3 textboxes txtSkill1, txtSkill2, txtSkill3
Sub ReadTextFile()
Dim lineCount As Integer = 0
Dim rndInstance As New Random
Dim idx As Integer = 0
Dim selectedLine As String = ""
Dim txt As String = "Skills.txt"
If Not File.Exists(txt) Then
File.Create(txt).Dispose()
Dim objWriter As New System.IO.StreamWriter(txt, True)
' 2 sample text lines:
objWriter.WriteLine("Negotiating - Interpersonal - Working independently")
objWriter.WriteLine("Goal oriented - Leadership - Teamwork")
objWriter.Close()
End If
lineCount = File.ReadAllLines(txt).Length
idx = rndInstance.Next(1, lineCount + 1) ' the index can be random if you want, or run from (1 to lineCount)
selectedLine = ReadLineWithNumberFrom(txt, idx)
Dim pattern As String = "-" ' split on hyphens
Dim subStrings() As String = Regex.Split(selectedLine, pattern)
txtSkill1.Text = subStrings(0)
txtSkill2.Text = subStrings(1)
txtSkill3.Text = subStrings(2)
End Sub
One can read a string from a specific line number:
Function ReadLineWithNumberFrom(filePath As String, ByVal lineNumber As Integer) As String
Using file As New StreamReader(filePath)
' Skip all preceding lines:
For i As Integer = 1 To lineNumber - 1
If file.ReadLine() Is Nothing Then
Throw New ArgumentOutOfRangeException("lineNumber")
End If
Next
' Attempt to read the line you're interested in:
Dim line As String = file.ReadLine()
If line Is Nothing Then
Throw New ArgumentOutOfRangeException("lineNumber")
End If
' Succeeded!
Return line
End Using
End Function
Now with the functions allow you to write to any text file, to read from any text file, from any line number, with specific separator (here is the hyphen -- char), you can Save and Load any string you need.

Searching for and deleting data within a text file

I am currently working on a Library Inventory System. I wanted it to be able to add, issue, search and delete book records. The records are stored in a text file which looks like this:
(ID), (Name Of Book); (Author); (Price) ; (Book Donor) ; (Language)
E.g.
123 , Journey to the center of the earth ; Jules Verne ; 50 ; Jack ; English
...
This program also works with a datagridview to update to/from the text file, so far my add and issue functions are working but i am having trouble with search and delete.
To search, the user must either enter the ID of the book in a textbox or the language of the book (separate textbox) and it must show the search results in the datagridview.
This is the my attempt for the search function:
Dim line As String
Dim fields(7) As String
Dim found As Boolean = False
Dim inputStream As StreamReader
inputStream = File.OpenText("AddBookScreen.txt")
line = inputStream.ReadLine()
While (line <> Nothing) And found = False
fields = Split(line, ",")
If Trim(fields(0)) = SBidTextbox.Text Then
SBdatagridview.Rows.Add(Trim(fields(1)), Trim(fields(2)), Trim(fields(3)), Trim(fields(4)), Trim(fields(5)), Trim(fields(6)))
found = True
Else
line = inputStream.ReadLine()
End If
End While
If Not found Then
MessageBox.Show(SBidTextbox.Text & " not found")
End If
inputStream.Close()
End Sub
The delete function should be able to find the specific book by id and then delete that record from the text file.
This is my attempt for the delete function:
Dim lines() As String
Dim outputlines As New List(Of String)
Dim searchString As String = DBidTextbox.Text
lines = IO.File.ReadAllLines("AddBookScreen.txt")
For Each line As String In lines
If line.Contains(searchString) = False Then
outputlines.Add(line)
End If
Next
The search and delete methods are meant to search for a specific book in the text file by either the ID of the book or the language and display the results in the datagridview, the delete method is to search for a specific record through ID and delete that record.
Could someone please guide me through these problems, your help would be much appreciated.
If you can change your text file format slightly (Only use one kind of delimiter - either comma or semi-colon), then you can use the Microsoft Text Driver. This allows you to treat the text file like a database table, and you can use SQL statements to SELECT, DELETE, or UPDATE. Below is an example:
Public Sub Delete(ByVal ID As String)
Dim SQL As String = String.Format("DELETE FROM myfile.csv WHERE ID={0}", ID)
Dim conn_str As String = String.Format("Driver={{Microsoft Text Driver (*.txt; *.csv)}};Dbq={0};Extensions=asc,csv,tab,tsv,txt;", folder)
Dim conn As New OdbcConnection(conn_str)
conn.Open()
Dim cmd As New OdbcCommand(sqltxt, conn)
Dim reader As OdbcDataReader = cmd.ExecuteNonQuery()
...
End Sub
If this system has any publicly facing user input, I would definitely recommend using a Parameterized Query to prevent SQL injection attacks.

VBNET Reading a specific column on a line in a text file

I have saved written a text file and it currently reads:
"first","surname","pass"
I want to read the password column so the 3rd one and define that as a variable. Its basically for a login, if pass in text file matches the entered pass (from user).
I have searched for about an hour now and no luck. Could someone guide me to a correct path.
Thanks.
Simple example of reading a small file line by line and splitting each one into fields:
' get the values from the user somehow:
Dim first As String = "James"
Dim surname As String = "Bond"
Dim pass As String = "007"
Dim validated As Boolean = False ' assume wrong until proven otherwise
' check the file:
Dim fileName As String = "c:\some folder\path\somefile.txt"
Dim lines As New List(Of String)(System.IO.File.ReadAllLines(fileName))
For Each line As String In lines
Dim values() As String = line.Split(",")
If values.Length = 3 Then
If values(0).Trim(Chr(34)) = first AndAlso
values(1).Trim(Chr(34)) = surname AndAlso
values(2).Trim(Chr(34)) = pass Then
validated = True
Exit For
End If
End If
Next
' check the result
If validated Then
MessageBox.Show("Login Successful!")
Else
MessageBox.Show("Login Failed!")
End If
If this is a CSV file, as seems to be the case, then the easiest way to read it will be with the TextFieldParser class. The MSDN already provides an excellent example for how to use it to read a CSV file, so I won't bother reproducing it here.

VB.NET: How to find a word after a specific word in a line and store it

I have a continuous string of words coming from a machine to hyper terminal of my system, for which I am using USB to serial cable. I want to find some of the values which comes after a specific word in that string and then store it.
I used threads and splitting concepts to do it but as per the requirement and operation of the machine it will not work properly in the runtime.
The values which I want to capture comes from a specific word. I want to skip that words and just store the values. How to do it?
I have given the example of that string below:
MEAN 49 50
SD 500 10
MIN 100 5
MAX 50 45.56
In this I just want to store the values e.g. 49 and 50, then discard MEAN. Then discard SD and store 500 and 10 and so on.
You can use a StreamReader object to read the stream one line at a time. Then, you can easily parse the line using the String.Split method. I would recommend creating one or more classes that represent the data being read, like this:
Public Class LineData
Public Property Label As String
Public Property Value1 As Decimal
Public Property Value2 As Decimal
End Class
Public Function ReadNextLine(stream As Stream) As LineData
Dim reader As New StreamReader(stream)
Dim line As String = reader.ReadLine()
Dim data As LineData = Nothing
If line IsNot Nothing Then
Dim words() As String = line.Split(New Char() {" "c}, StringSplitOptions.RemoveEmptyEntries)
If words.Length = 3 Then
data = New LineData()
data.Label = words(0)
data.Value1 = Decimal.Parse(words(1))
data.Value2 = Decimal.Parse(words(2))
End If
End If
Return Data
End Function
Note, this is a very simple example based on the example data you provided. If different lines have different numbers of numeric parameters, that will further complicate the logic. In my example, the method returns Nothing if no data can be read. Also, the method will throw an exception if the last two words in the line are not numeric. Therefore, you would need to wrap it in some additional exception handling.
This may be what you're looking for. Although personally I'd create a class which stores the type(mean, median etc), firstvalue and secondvalue.
By the sounds of it though, all you want it to do is dump the values into some sort of storage, therefore this will suffice.
Dim Values as New List(Of Decimal)
'Use a streamreader to read each line of text
Using reader As StreamReader = New StreamReader(*your text source*)
'Read the line
Dim linetext as string = reader.ReadLine
Dim myValue as decimal
'Split the line
Dim splitText() = linetext.Split(" ")
'Analyze each section of the line, if its possible to parse the value as a decimal then add it to the list of values to be stored.
For Each txt in splitText
If Decimal.TryParse(txt, myValue) then Values.Add(myValue)
Next
End Using

VB.NET - Load a List of Values from a Text File

I Have a text file that is like the following:
[group1]
value1
value2
value3
[group2]
value1
value2
[group3]
value3
value 4
etc
What I want to be able to do, is load the values into an array (or list?) based on a passed in group value. eg. If i pass in "group2", then it would return a list of "value1" and "value2".
Also these values don't change that often (maybe every 6 months or so), so is there a better way to store them instead of a plain old text file so that it makes it faster to load etc?
Thanks for your help.
Leddo
This is a home work question?
Use the StreamReader class to read the file (you will need to probably use .EndOfStream and ReadLine()) and use the String class for the string manipulation (probably .StartsWith(), .Substring() and .Split().
As for the better way to store them "IT DEPENDS". How many groups will you have, how many values will there be, how often is the data accessed, etc. It's possible that the original wording of the question will give us a better clue about what they were after hear.
Addition:
So, assuming this program/service is up and running all day, and that the file isn't very large, then you probably want to read the file just once into a Dictionary(of String, List(of String)). The ContainsKey method of this will determine if a group exists.
Function GetValueSet(ByVal filename As String) As Dictionary(Of String, List(Of String))
Dim valueSet = New Dictionary(Of String, List(Of String))()
Dim lines = System.IO.File.ReadAllLines(filename)
Dim header As String
Dim values As List(Of String) = Nothing
For Each line As String In lines
If line.StartsWith("[") Then
If Not values Is Nothing Then
valueSet.add(header, values)
End If
header = GetHeader(line)
values = New List(Of String)()
ElseIf Not values Is Nothing Then
Dim value As String = line.Trim()
If value <> "" Then
values.Add(value)
End If
End If
Next
If Not values Is Nothing Then
valueSet.add(header, values)
End If
Return valueSet
End Function
Function GetHeader(ByVal line As String)
Dim index As Integer = line.IndexOf("]")
Return line.Substring(1, index - 1)
End Function
Addition:
Now if your running a multi-threaded solution (that includes all ASP.Net solutions) then you either want to make sure you do this at the application start up (for ASP.Net that's in Global.asax, I think it's ApplicationStart or OnStart or something), or you will need locking. WinForms and Services are by default not multi-threaded.
Also, if the file changes you need to restart the app/service/web-site or you will need to add a file watcher to reload the data (and then multi-threading will need locking because this is not longer confined to application startup).
ok, here is what I edned up coding:
Public Function FillFromFile(ByVal vFileName As String, ByVal vGroupName As String) As List(Of String)
' open the file
' read the entire file into memory
' find the starting group name
Dim blnFoundHeading As Boolean = False
Dim lstValues As New List(Of String)
Dim lines() As String = IO.File.ReadAllLines(vFileName)
For Each line As String In lines
If line.ToLower.Contains("[" & vGroupName.ToLower & "]") Then
' found the heading, now start loading the lines into the list until the next heading
blnFoundHeading = True
ElseIf line.Contains("[") Then
If blnFoundHeading Then
' we are at the end so exit the loop
Exit For
Else
' its another group so keep going
End If
Else
If blnFoundHeading And line.Trim.Length > 0 Then
lstValues.Add(line.Trim)
End If
End If
Next
Return lstValues
End Function
Regarding a possible better way to store the data: you might find XML useful. It is ridiculously easy to read XML data into a DataTable object.
Example:
Dim dtTest As New System.Data.DataTable
dtTest.ReadXml("YourFilePathNameGoesHere.xml")