[RESOLVED] reading an individual field
He everyone,
Sorry if this is in the wrong spot i believe this is the proper spot. anyways, i am using the code below to read a text file and then separate the line where it finds a :: - my problem is what if i have a line like:
FilePath=C:\file.txt::Name=Text::Subject=CIM
I would like to display the Name on a list box and when it is selected then the file can be opened, my problem is i don't know how to get just the Name= part without getting everything else.
Help would be greatly appreciated and if you require any more information please let me know.
Code:
Private Function read()
Dim FILE_NAME As String = My.Application.Info.DirectoryPath & "\FileInfo.txt"
Dim txtfile As New System.IO.StreamReader(FILE_NAME)
Dim textline As String
Do While txtfile.Peek() <> -1
textline = txtfile.ReadLine()
'------------------------
If textline.StartsWith("Filepath=") Then
Dim modtextline As String
modtextline = Replace(textline, "Filepath=", "")
Dim fields() As String
fields = Split(modtextline, "::")
End If
Loop
End Function
File Contents are:
SubjectNames=CIM::Chemistry::Trigonometry
Filepath=C:\file.txt::Name=1::Subject=CIM
It would be nice to only need to have Filepath=C:\file.txt::FileName::CIM just because i am manually entering lines right now until i ocmplete the rest of the program, plus i would like to only have it search for the line that starts with Filepath= so then it knows that this line it needs to read
Re: reading an individual field
Thread moved from 'VB6 and Earlier' forum to 'VB.Net' (VB2002 and later) forum
Re: reading an individual field
Thank you and sorry, I though VB.net was a totally different thing from Visual Basic
Re: reading an individual field
This is the sort of area where LINQ excels because it lets you do a lot of work in a very small amount of code with no loops:
vb.net Code:
myListBox.DisplayMember = "Name"
myListBox.ValueMember = "Filepath"
myListBox.DataSource = (From line In IO.File.ReadAllLines("file path here") _
Where line.StartsWith("Filepath") _
Let parts = line.Split(New String() {"::"}, StringSplitOptions.None) _
Select New With {.Filepath = parts(0).Split("="c)(1), _
.Name = parts(1).Split("="c)(1)}).ToArray()
So basically, that code reads all the lines from the file, discards those that don't begin with "Filepath", splits each of those lines into an array on the "::" delimiter, splits the first and second elements of that array on the the "=" delimiter, creates a new object with Filepath and Name properties containing the second elements from those last splits, puts all those objects into an array and then binds that to the ListBox, and that's just the third line. The first two lines mean that the ListBox will display the Name properties of each of the bound objects and also that, when the user selects a Name, you can get the corresponding Filepath from the SelectedValue of the ListBox. Like I said, a lot of work in a small amount of code.
Just note that LINQ requires .NET 3.5 or higher, so you must also be using VB 2008 or later.
Re: reading an individual field
Thank you! I will give it a try and report back later today :)
It may have been a good idea for me to say that i am using visual studio 2010 professional, I get a message that let and set statements are not longer supported.
Edit Again: I retyped all the code, instead of copy/paste/remove numbers, and i get no errors! :) i will post back soon!
Re: reading an individual field
Quote:
Originally Posted by
jmcilhinney
This is the sort of area where LINQ excels because it lets you do a lot of work in a very small amount of code with no loops:
vb.net Code:
myListBox.DisplayMember = "Name"
myListBox.ValueMember = "Filepath"
myListBox.DataSource = (From line In IO.File.ReadAllLines("file path here") _
Where line.StartsWith("Filepath") _
Let parts = line.Split(New String() {"::"}, StringSplitOptions.None) _
Select New With {.Filepath = parts(0).Split("="c)(1), _
.Name = parts(1).Split("="c)(1)}).ToArray()
So basically, that code reads all the lines from the file, discards those that don't begin with "Filepath", splits each of those lines into an array on the "::" delimiter, splits the first and second elements of that array on the the "=" delimiter, creates a new object with Filepath and Name properties containing the second elements from those last splits, puts all those objects into an array and then binds that to the ListBox, and that's just the third line. The first two lines mean that the ListBox will display the Name properties of each of the bound objects and also that, when the user selects a Name, you can get the corresponding Filepath from the SelectedValue of the ListBox. Like I said, a lot of work in a small amount of code.
Just note that LINQ requires .NET 3.5 or higher, so you must also be using VB 2008 or later.
Well it had no errors when i put the code in but i get "Index was outside the bounds of the array" and then part highlighted in yellow is bolded below
Code:
ListBox1.DisplayMember = "Name"
ListBox1.ValueMember = "Filepath"
ListBox1.DataSource = (From line In IO.File.ReadAllLines(My.Application.Info.DirectoryPath & "\FileInfo.txt") Where line.StartsWith("Filepath") Let parts = line.Split(New String() {"::"}, StringSplitOptions.None)
Select New With {.filepath = parts(0).Split("="c)(1), .Name = parts(1).Split("="c)(1)}).ToArray()
Any suggestions?
Re: reading an individual field
That means that there is at least one line in your data that starts with "Filepath" but either doesn't contain a "::" delimiter or, having split the line on the "::", one of the first two parts doesn't contain a "=" delimiter. You need to look at your data and write the code to not only extract the data you want but also to not choke on the data you don't want. The code I provided can handle date where every line that starts with "Filepath" begins with the format "Filepath=X::Y=Z". If some lines that start with "Filepath" don't have that format then the code will need changing, but we can only work with the information we have.
Re: reading an individual field
Quote:
Originally Posted by
jmcilhinney
That means that there is at least one line in your data that starts with "Filepath" but either doesn't contain a "::" delimiter or, having split the line on the "::", one of the first two parts doesn't contain a "=" delimiter. You need to look at your data and write the code to not only extract the data you want but also to not choke on the data you don't want. The code I provided can handle date where every line that starts with "Filepath" begins with the format "Filepath=X::Y=Z". If some lines that start with "Filepath" don't have that format then the code will need changing, but we can only work with the information we have.
The first line in my code is
Quote:
SubjectNames=CIM::Chemistry::Trigonometry
if that is the reason y i am having problems i can simply remove that line from that file and have my first form check a difernet file or even code it into the program
Re: reading an individual field
Read what I posted:
Quote:
That means that there is at least one line in your data that starts with "Filepath" but...
As I stated, my code is ignoring any lines that don;t start with "Filepath", so the problem is with one of the lines that DOES start with "Filepath" not meeting one of the other requirements. I have stated what those other requirements are.
Re: reading an individual field
Quote:
Originally Posted by
jmcilhinney
Read what I posted:As I stated, my code is ignoring any lines that don;t start with "Filepath", so the problem is with one of the lines that DOES start with "Filepath" not meeting one of the other requirements. I have stated what those other requirements are.
O yes i double checked my file and i must not have saved it. thank you i will try this now and see what happens.
Re: reading an individual field
okay, so in my listbox it shows the value of name= (which for testing i did Filepath=filepath::Name=name
Now i am confued on how i can get filepath to show up in a text label. i am guessing it has to do with these two line but i am not to sure how that worked
Code:
ListBox1.DisplayMember = "Name"
ListBox1.ValueMember = "Filepath"
Re: reading an individual field
No, it doesn't have to do with those two lines. Those two lines control how the bound ListBox behaves. DisplayMember is the name of the property or column whose data should be displayed, hence you see the Name values in the ListBox. ValueMember is the name of the property or column whose data should be exposed via the SelectedValue, hence when the user selects a Name you can get the corresponding Filepath from the SelectedValue of the ListBox.
If you wanted to do things the hard way, you could handle the SelectedIndexChanged event of the ListBox, get the SelectedValue and then display that in the Label. If you've already bound the ListBox though, it's only logical to bind the Label as well. Instead of assigning the array to the DataSource of the ListBox directly, assign it to a variable first. You can then bind it to both the ListBox and the Label:
vb.net Code:
Dim items = (From ...).ToArray()
ListBox1.DataSource = items
Label1.DataBindings.Add("Text", items, "Filepath")
Once bound, the Label will always display the Filepath of the item selected in the ListBox.
Re: reading an individual field
Quote:
Originally Posted by
jmcilhinney
No, it doesn't have to do with those two lines. Those two lines control how the bound ListBox behaves. DisplayMember is the name of the property or column whose data should be displayed, hence you see the Name values in the ListBox. ValueMember is the name of the property or column whose data should be exposed via the SelectedValue, hence when the user selects a Name you can get the corresponding Filepath from the SelectedValue of the ListBox.
If you wanted to do things the hard way, you could handle the SelectedIndexChanged event of the ListBox, get the SelectedValue and then display that in the Label. If you've already bound the ListBox though, it's only logical to bind the Label as well. Instead of assigning the array to the DataSource of the ListBox directly, assign it to a variable first. You can then bind it to both the ListBox and the Label:
vb.net Code:
Dim items = (From ...).ToArray()
ListBox1.DataSource = items
Label1.DataBindings.Add("Text", items, "Filepath")
Once bound, the Label will always display the Filepath of the item selected in the ListBox.
Okay that makes some more sense, thank you. So for example if i added Subject= to the text string
Filepath=filepath1::Name=name1::Subject=subject1
i could have a second label and do
vb.net Code:
label2.databindings.add("Text", items, "Subject")
and for the other code
vb.net Code:
Select New With {.filepath = parts(0).Split("="c)(1), .Name = parts(1).Split("="c)(1), .Subject = parts(2).Split("="c)(2)}).ToArray()
Correct?
Thank you so much for your help and time! :D
Re: reading an individual field
That's the right idea and nearly the right implementation. The only bit you got wrong was here:
Code:
.Subject = parts(2).Split("="c)(2)
which should have been:
Code:
.Subject = parts(2).Split("="c)(1)
When you split the original line and assign the result 'parts' you're turning this single string:
Code:
Filepath=filepath1::Name=name1::Subject=subject1
into these three string:
Code:
Filepath=filepath1
Name=name1
Subject=subject1
Those three string are at indexes 0, 1 and 2, which is why you use parts[0], parts[1] and parts[2].
When you then split one of those strings on the '=' you split one string into two, e.g.becomes:The name of the field is at index 0 and the value is at index 1, so to get the value of the Subject field you get the element at index 2 from 'parts', split it and then get the element at index 1 of the result.
Re: reading an individual field
ah thank you i did not go back to the first split to see about that second number but it makes more sense. Thank you so much! My last question is what if i would like to sort them so say i select CIM from the previous form which opens up the form with listbox1 on it.
I am guessing i could do an if statement but i am unsure how to do
vb.net Code:
If Subject= vbinder then
...
End If
then have it do the label bindings and listbox1. Though a thought, wouldn't i have to move the code below down below where it splits up the string so that it is not added unless the criteria is met? i have a variable called "vbinder" that stores which subject was selected on form1
vb.net Code:
ListBox1.DisplayMember = "Name"
ListBox1.ValueMember = "Filepath"
Re: [RESOLVED] reading an individual field
Thanks jmcilhinney!
I have figured out the answer to my last question posted.
Here it is:
Have a for each loop and have it select the item and check the label associated with the subject and if it isn't for the subject i asked it deletes it and goes on to the next item