Question

I am developing an application to read a text file and plot a graph. the text file will be something like

#Pattern Name Item1, Item2, Item3, gx1, gy1, gz1 
115, 80, 64, 30.752, 27.587, 15.806 
195, 151, 130, 108.983, 102.517, 66.353 
94, 123, 156, 43.217, 50.874, 93.700 
88, 108, 65, 26.158, 37.980, 17.288 
130, 129, 177, 68.096, 66.289, 127.182 
100, 190, 171, 71.604, 119.764, 122.349 
.........................................
........................................
#Pattern Name2 Item1, Item2, Item3, gx1, gy1, gz1 
115, 80, 64, 30.752, 27.587, 15.806 
195, 151, 130, 108.983, 102.517, 66.353 
94, 123, 156, 43.217, 50.874, 93.700 
88, 108, 65, 26.158, 37.980, 17.288 
130, 129, 177, 68.096, 66.289, 127.182 
100, 190, 171, 71.604, 119.764, 122.349

etc.

I need the value gx1,gy1 . I planned to read them by counting spaces and commas (3 each). But Does it sounds in appropriate? Is there any optimized or more good logic for that?

Was it helpful?

Solution 2

You should use an existing csv-parser like this.

However, assuming that the name of the pattern is unique and you want to acess it later:

var gxDict = new Dictionary<string, List<Tuple<double, double>>>();
List<Tuple<double, double>> currentGxList = null;
foreach (string line in File.ReadLines(filePath))
{
    if (line.StartsWith("#Pattern"))
    {
        string[] headers = line.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
        string patternField = headers.First();
        string patterName = string.Join(" ", patternField.Split().Skip(1).Take(2));
        List<Tuple<double, double>> gxList = null;
        if (gxDict.TryGetValue(patterName, out gxList))
            currentGxList = gxList;
        else
        {
            currentGxList = new List<Tuple<double, double>>();
            gxDict.Add(patterName, currentGxList);
        }
    }
    else
    {
        if (currentGxList != null)
        {
            string[] values = line.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            double gx1;
            double gy1;
            string gx1Str = values.ElementAtOrDefault(3);
            string gy1Str = values.ElementAtOrDefault(4);
            if (double.TryParse(gx1Str, out gx1) && double.TryParse(gx1Str, out gy1))
            {
                currentGxList.Add(Tuple.Create(gx1, gy1));
            }
        }
    }
}

// now you can access it in this way:

List<Tuple<double, double>> nameItem1Vals = gxDict["Name Item1"];
foreach (var xy in nameItem1Vals)
    Console.WriteLine("gx1: {0} gy1: {1}", xy.Item1, xy.Item2);

// or in a loop:

foreach (var kv in gxDict)
{
    string pattern = kv.Key;
    Console.WriteLine("pattern: {0}", pattern);
    foreach (var xy in nameItem1Vals)
        Console.WriteLine("gx1: {0} gy1: {1}", xy.Item1, xy.Item2);
}

Note that i avoid Linq when it comes to IO where you need event handling on file level and when i try to parse input which could also cause exceptions.

OTHER TIPS

How about using Linq?

var allparts = File.ReadLines(filename)
                .Where(line => !line.StartsWith("#"))
                .Select(line => line.Split(','))
                .Select(parts => new {gx1=parts[3], gy1=parts[4]} ) 
                .ToList();

What you have is a simple CSV file. I would recommend either:

1) Using a CSV parsing library (for example http://www.filehelpers.com/)
2) Parsing this yourself on a line by line basis:

String[] lines = File.ReadAllLines(...);
foreach(String line in lines)
{
   String parts[] = line.Split(",", StringSplitOptions.IgnoreEmpty);
   double gx1 = Double.Parse(parts[5]);
   double gx2 = Double.Parse(parts[6]);
}

You will however need to add in some validation / line skipping for your special lines

What about reading each line and then line.Split(", ")? Sou you can have:

var items = line.Split(", ");
var gx1 = items[3];
var gy1 = items[4];
var gz1 = items[5];
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top