问题
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?
回答1:
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.
回答2:
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();
回答3:
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
回答4:
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];
来源:https://stackoverflow.com/questions/16211382/parsing-text-file-separated-by-comma