2013-04-25 6 views
0

Я разрабатываю приложение для чтения текстового файла и построения графика. текстовый файл будет что-то вродеРазбор текстового файла, разделенного запятой

#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 

т.д.

мне нужно значение GX1, GY1. Я планировал их прочитать, посчитав пробелы и запятые (3 каждый). Но звучит ли это правильно? Есть ли оптимизированная или более хорошая логика для этого?

+0

Являются ли имена столбцов повторяющимися в середине файла? – Ash

+0

Один из вариантов - встроенный класс 'TextFieldParser' http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.fileio.textfieldparser.aspx –

+0

@Ash Я не получаю то, что вы сказали – Zigma

ответ

1

Вы должны использовать существующий CSV-анализатор, как this.

Однако, если предположить, что имя шаблона является уникальным, и вы хотите Асесс позже:

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)); 
      } 
     } 
    } 
} 

// Теперь вы можете получить доступ к нему таким образом:

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

// или в цикле:

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); 
} 

Следует заметить, что я избежать Linq, когда дело доходит до IO, где вам нужно еи а также при попытке проанализировать ввод, который также может вызвать исключения.

+0

Edit: 'if (int.TryParse (gx1Str, out gx1) && int.TryParse (gy1Str, out gy1))'. Также значения являются двойными по типу, как вы можете видеть в вопросе – Zigma

+0

@ Zigma: Спасибо. Отредактировал мой ответ. –

+0

Я не могу принять значения. Мне нужно, чтобы они передавали его в [DataBindXY] (http://msdn.microsoft.com/en-IN/library/system.web.ui.datavisualization.charting.datapointcollection.databindxy.aspx) метод как x, y. – Zigma

2

Как насчет использования 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

Плохое исполнение. Читайте строки за строкой. Когда данные поступают в CSV и это не образец студента, тогда файл CSV может иметь огромные размеры. – Regfor

+3

@Regfor 'ReadLines' уже делает это по строкам. Это не 'File.ReadAllLines' – I4V

+0

, вы правы. + для этого :) – Regfor

1

У вас есть простой CSV-файл. Я бы рекомендовал либо:

1) Использование разбора библиотеки CSV (например http://www.filehelpers.com/)
2) Синтаксическое это непосредственно на прямой линии основе:

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]); 
} 

Вам однако нужно добавить в некоторых валидация/прокрутка строк для ваших специальных линий

+1

ReadAllLines == Плохо perfromance – Regfor

+0

@Regfor: Плохая производительность по сравнению с чем? Я знаю, что это повлияет на память, но в какой-то момент каждая строка должна быть прочитана сразу или по одному ... –

+0

Файл CSV может быть огромным.Когда наступает огромный файл CSV - объем памяти огромен, производительность медленная по сравнению с линией. – Regfor

0

Как насчет чтения каждой строки, а затем строки.Split (",")? Sou вы можете иметь:

var items = line.Split(", "); 
var gx1 = items[3]; 
var gy1 = items[4]; 
var gz1 = items[5]; 
Смежные вопросы