I have a program that reads texts files and I'm wanting it to collect data after a certain title in the text file, in this case [HRData]
. Once the streamreader reaches [HRData]
I want it to read every line after that and store each line in a list, but allowing me to get access to the seperate numbers.
The text file is like so:
[HRZones]
190
175
162
152
143
133
0
0
0
0
0
[SwapTimes]
[Trip]
250
0
3978
309
313
229
504
651
//n header
[HRData]
91 154 70 309 83 6451
91 154 70 309 83 6451
92 160 75 309 87 5687
94 173 80 309 87 5687
96 187 87 309 95 4662
100 190 93 309 123 4407
101 192 97 309 141 4915
103 191 98 309 145 5429
So referring to the text file, I want it to store the first line after [HRData] and allow me access each variable, for example 91
being [0]
.
I have code that already stores to a list if the word matches the regex, but I do not know how to code it to read after a specific string like [HRData].
if (squareBrackets.Match(line).Success) {
titles.Add(line);
if (textAfterTitles.Match(line).Success) {
textaftertitles.Add(line);
}
}
This is my attempt so far:
if (line.Contains("[HRData]")) {
inttimes = true;
MessageBox.Show("HRDATA Found");
if (inttimes == true) {
while (null != (line = streamReader.ReadLine())) {
//ADD LINE AND BREAK UP INTO PARTS S
}
}
}
Presuming your current code attempt works, which I have not gone through to verify...
You could simply do the following:
List<int> elements = new List<int>();
while (null != (line = streamReader.ReadLine()))
{
if(line.Contains("["))
{
//Prevent reading in the next section
break;
}
string[] split = line.Split(Convert.ToChar(" "));
//Each element in split will be each number on each line.
for(int i=0;i<split.Length;i++)
{
elements.Add(Convert.ToInt32(split[i]));
}
}
Alternatively, if you want a 2 dimensional list, such that you can reference the numbers by line, you could use a nested list. For each run of the outer loop, create a new list and add it to elements (elements would be List<List<int>>
).
Edit
Just a note, be careful with the Convert.ToInt32() function. It should really be in a try catch statement just in case some text is read in that isn't numeric.
Edit
Ok.. to make the routine more robust (per my comment below):
First make sure the routine doesn't go beyond your block of numbers. I'm not sure what is beyond the block you listed, so that will be up to you, but it should take the following form:
If(line.Contains("[") || line.Contains("]") || etc etc etc)
{
break;
}
Next thing is pre-format your split values. Inside the for statement:
for(int i=0;i<split.Length;i++)
{
string val = split[i].Trim(); //Get rid of white space
val = val.Replace("\r\n",""); //Use one of these to trim every character.
val = val.Replace("\n","");
try
{
elements.Add(Convert.ToInt32());
}
catch (Exception ex)
{
string err = ex.Message;
//You might try formatting the split value even more here and retry convert
}
}
To access the individual numbers (presuming you are using a single dimension list) there are a couple ways to do this. If you want to access by index value:
elements.ElementAt(index)
if you want to iterate through the list of values:
foreach(int val in elements)
{
}
If you need to know exactly what line the value came from, I suggest a 2d list. It would be implemented as follows (I'm copying my code from the original code snippet, so assume all of the error checking is added!)
List<List<int>> elements = new List<List<int>>();
while (null != (line = streamReader.ReadLine()))
{
if(line.Contains("["))
{
//Prevent reading in the next section
break;
}
List<int> newLine = new List<int>();
string[] split = line.Split(Convert.ToChar(" "));
//Each element in split will be each number on each line.
for(int i=0;i<split.Length;i++)
{
newLine.Add(Convert.ToInt32(split[i]));
}
elements.Add(newLine);
}
Now to access each element by line:
foreach(var line in elements)
{
//line is a List<int>
int value = line.ElementAt(index); //grab element at index for the given line.
}
Alternatively, if you need to reference directly by line index, and column index
int value = elements.ElementAt(lineIndex).ElementAt(columnIndex);
Be careful with all of these direct index references. You could pretty easily get an index out of bounds issue.
One other thing.. you should probably put a breakpoint on your Convert.ToInt statement and find what string it is breaking on. If you can assume that the data input will be consistent, then finding exactly what string is breaking the conversion will help you create a routine that handles the particular characters that are filtering in. I am going to guess that the method broke when it attempted to Convert the last split value to an integer, and we had not removed line endings.