c# reading text file into arrays [duplicate] - c#

This question already has answers here:
2d Array from text file c# [closed]
(3 answers)
Closed 9 years ago.
How can I loop through a text file to create six arrays from the content of the text file.
For example, the text file will look like this but with more lines(without title) maybe 200 of them
top_speed average_speed cadence altitude heart_rate power
84 73 0 -124 0 50
86 179 84 -125 121 3893
It would be nice to have an array for each. So, for example
top_speed = 84 + 86 : average_speed = 73 + 179 ... (and so on)
What's the best way to do this?

Anyway, if that is homework, following code will not help you :) But if it is not homework, you will understand how to parse such files with LINQ
var items =
File.ReadAllLines(filename) // read lines from file
.Select(line => line.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries)
.Select(Int32.Parse)
.ToArray()) // convert each line to array of integers
.Select(values => new {
TopSpeed = values[0],
AverageSpeed = values[1],
Cadence = values[2],
Altitude = values[3],
HeartRate = values[4],
Power = values[5]
}); // create anonymous object with nice strongly-typed properties
int[] topSpeeds = items.Select(i => i.TopSpeed).ToArray();

You could create a Record class and then use a simple LINQ query:
var records = File.ReadLines("file.txt")
.Select(line =>
{
string[] parts = line.Split('\t');
return new Record
{
TopSpeed = int.Parse(parts[0]),
AverageSpeed = int.Parse(parts[1]),
Cadence = int.Parse(parts[2]),
Altitude = int.Parse(parts[3]),
HeartRate = int.Parse(parts[4]),
Power = int.Parse(parts[5])
};
}).ToArray();
This will give you a bunch of Records, one per line in the original file. If you wanted to then check all of HeartRates for building a histogram or graphing or whatever, you could grab them like this:
var allHeartRates = records.Select(rec => rec.HeartRate);

Related

Reading double Numbers from a text file which contains string and number mixed

I have a file which contains Numbers and Texts. and I'm trying to read all numbers as double and put them in a one dimension double array.
In the file , some lines begin with Space. also some lines contain Two or Three numbers after each other.
The file is creating from another app which i don't want to change its output format.
The data in the file is like blow and some lines begin with some space :
110 ! R1
123.000753 ! Radian per s as R2
600.0451 65 ! j/kg
12000 ! 4 Number of iteration
87.619 ! (min 20 and max 1000)
My code so far is :
char[] splits = { ' ', '!' };
var array = File.ReadAllLines(#"myfile.dat")
.SelectMany(linee => linee.Split(splits))
.Where(n => !string.IsNullOrWhiteSpace(n.ToString()))
.Select(n =>
{
double doub;
bool suc = double.TryParse(n, out doub);
return new { doub, suc };
}).Where( values=>values.suc).ToArray();
The problem is that my code also read numbers after ! in the descriptions like line 4 and line 5.
Array have to be like this :
110 , 123.000735 , 6000.0451 , 65 , 120000 , 87.619
But in my code is like this :
110 , 123.000735 , 6000.0451 , 65 , 120000 , 4 , 87.619 , 20 , 1000
It's hard to give a general formula when given only a single example, but the following will work for your example:
return File.ReadLines(#"myfile.dat")
.Where(s => !String.IsNullOrWhiteSpace(s))
.Select(s => s.Substring(0, s.IndexOf('!')).Split(new [] {' '}, StringSplitOptions.RemoveEmptyEntries))
.SelectMany(s => s)
.Select(s => Double.Parse(s));
One approach could be as following.
var lines = str.Split(new []{"!",Environment.NewLine},StringSplitOptions.RemoveEmptyEntries)
.Where(x=> x.Split(new []{" "},StringSplitOptions.RemoveEmptyEntries).All(c=>double.TryParse(c, out _))).
SelectMany(x=> x.Split(new []{" "},StringSplitOptions.RemoveEmptyEntries).Select(c=>double.Parse(c)));
Here's an alternate solution using regular expressions:
var regex = new Regex(#"^(\s*(?<v>\d+(\.\d+)?)\s*)+\!.*$");
var query = from line in lines
let match = regex.Match(line)
where match.Success
from #group in match.Groups.Cast<Group>()
where #group.Name == "v"
select double.Parse(#group.Value, NumberStyles.Float, CultureInfo.InvariantCulture);

Edit specific word in specific line

I know this has been asked a few times, but I'm need a fast way to do this in files with different size (small and large files).
I need to edit scale factor in sat(txt) file. This is a first number in third line:
700 104 1 0 16 Autodesk AutoCAD 19 ASM 221.0.0.1871 NT 24 Tue
Aug 16 09:02:14 2016
1000 9.9999999999999995e-007 1e-010
I suggest extracting a method and Linq:
private static String MyEditLine(string value) {
var items = value.Split(new char[] { ' ' }, 2);
items[0] = "2000"; // let's change 1000 into 2000
return string.Join(" ", items);
}
...
var target = File
.ReadLines(#"C:\MyFile.txt")
.Select((line, index) => index != 2
? line
: MyEditLine(line))
.ToList();
File.WriteAllLines(#"C:\MyFile.txt", target);
assume you read your file and get a String[] called file and the number, you want to modify, is represented as float.
Than you can use the following code to first extract the line, you want. After this you get the number through float.TryParse(..)
int lineWithParam = 3;
String[] splittedLine = (file[lineWithParam-1]).Split(new char[] { ' ' }, 2);
if(splittedLine.Length == 2)
{
float fact = 0.0f;
String newFact = splittedLine[0];
// or how ever you want to modify your factor
if(float.TryParse(splittedLine[0], out fact))
{
newFact = "" + (fact * 12.3f);
}
file[lineWithParam-1] = newFact + " " + splittedLine[1];
}
Here an executable example: https://dotnetfiddle.net/NVgETo
after this you can write the String[] file back to the real file.
Note: this will not modify the file, if in the given line the first parameter isn't a valid float!

Reading lines after specific string in a text file then storing data in lists

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
}
}
}
You can call a LINQ-friendly method File.ReadLines , then you can use LINQ to get the part you want:
List<string> numbers = File.ReadLines("data.txt")
.SkipWhile(line => line != "[HRData]")
.Skip(1)
.SelectMany(line => line.Split())
.ToList();
Console.WriteLine(numbers[0]); // 91
Edit - this will give you all the numbers in one List<string>, if you want to keep the line order, use Select instead of SelectMany:
List<List<string>> listsOfNums = File.ReadLines("data.txt")
.SkipWhile(line => line != "[HRData]")
.Skip(1)
.Select(line => line.Split().ToList())
.ToList();
Note that this requires additional index to get a single number:
Console.WriteLine(listsOfNums[0][0]); // 91
You could use a variable to track the current section:
var list = new List<int[]>();
using (StreamReader streamReader = ...)
{
string line;
string sectionName = null;
while (null != (line = streamReader.ReadLine()))
{
var sectionMatch = Regex.Match(line, #"\s*\[\s*(?<NAME>[^\]]+)\s*\]\s*");
if (sectionMatch.Success)
{
sectionName = sectionMatch.Groups["NAME"].Value;
}
else if (sectionName == "HRData")
{
// You can process lines inside the `HRData` section here.
// Getting the numbers in the line, and adding to the list, one array for each line.
var nums = Regex.Matches(line, #"\d+")
.Cast<Match>()
.Select(m => m.Value)
.Select(int.Parse)
.ToArray();
list.Add(nums);
}
}
}
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.

How Can I read From Line number() to line Starts with in C#

Let's say I have text file like this
<pre>----------------
hPa m C
---------------------
1004.0 28 13.6
1000.0 62 16.2
998.0 79 17.2
992.0 131 18.0
<pre>----------------
Sometext here
1000.0 10 10.6
1000.0 10 11.2
900.0 10 12.2
900.0 100 13.0
<aaa>----------------
How Can I Create Array in C# that reads text file from line number 5 (1004.0) to just before line that starts with string <pre>-
I used string[] lines = System.IO.File.ReadAllLines(Filepath);
To make each line in the array
The problem is I want only numbers of first section in the array in order to separate them later to another 3 arrays (hPa, m, C) .
Here's a possible solution. It's probably way more complicated than it should be, but that should give you an idea of possible mechanisms to further refine your data.
string[] lines = System.IO.File.ReadAllLines("test.txt");
List<double> results = new List<double>();
foreach (var line in lines.Skip(4))
{
if (line.StartsWith("<pre>"))
break;
Regex numberReg = new Regex(#"\d+(\.\d){0,1}"); //will find any number ending in ".X" - it's primitive, and won't work for something like 0.01, but no such data showed up in your example
var result = numberReg.Matches(line).Cast<Match>().FirstOrDefault(); //use only the first number from each line. You could use Cast<Match>().Skip(1).FirstOrDefault to get the second, and so on...
if (result != null)
results.Add(Convert.ToDouble(result.Value, System.Globalization.CultureInfo.InvariantCulture)); //Note the use of InvariantCulture, otherwise you may need to worry about , or . in your numbers
}
Do you mean this?
System.IO.StreamReader file = new System.IO.StreamReader(FILE_PATH);
int skipLines = 5;
for (int i = 0; i < skipLines; i++)
{
file.ReadLine();
}
// Do what you want here.

How to get value from number tagged file and compare it?

hi i'm trying to extract values from this tagged file
here is the file
0
LINE
5
1C1CBD
330
1C1ADB
100
AcDbEntity
8
0-FD
62
9
370
-2
100
AcDbLine
10
53740.73468153231
20
-190253.3098529756
30
0.0
11
53690.49919802765
21
-190166.2994431953
31
0.0
0
you can see that there is a hexadecimal number below "LINE", is there anyway i can extract it into some list?
like
VALUE = 1C1CBD
NOTE: the file consist more than one of this kind of pattern
and then how can i get the maximum value?
EDIT 1
i see that "5" can be found by using regex "\s\s5" can i use this?
Thank you for your feedback i have been able to complete what i want
here is the code
string[] handle = originalString.Split(new string[] { "\r\n" }, StringSplitOptions.None);
List<string> hexa = new List<string>();
for (var a = 1; a <= handle.Count() - 1; a++)
{
if (Regex.IsMatch(handle[a], #"^\s\s5"))
{
hexa.Add(handle[a + 1]);
}
}
List<int> HexaToInt = new List<int>();
foreach (string valueHexa in hexa)
{
int intHexaValue = int.Parse(valueHexa, System.Globalization.NumberStyles.HexNumber);
HexaToInt.Add(intHexaValue);
}
int maximumHexa = HexaToInt.Max();
string hexValue = maximumHexa.ToString("X");
it is possible afterall to extract the hexadecimal value from the handle group codes
It is totally impossible.
No way to catch characters and extract what you need.
You have to organize the structure of this file better.

Categories

Resources