using System; using System.Collections.Generic; using System.IO; using CsvHelper; using CsvHelper.Configuration; using LeafWeb.Core.Models; namespace LeafWeb.Core.Services { public class LeafInputCsvParser : IDisposable { private readonly FileSystemInfo _csvFile; private readonly StreamReader _reader; private readonly CsvReader _csv; public LeafInputCsvParser(FileSystemInfo csvFile) { _csvFile = csvFile; if (!csvFile.Exists) throw new FileNotFoundException("Cannot find file '" + csvFile.Name + "'"); _reader = File.OpenText(csvFile.FullName); var csvConfiguration = new CsvConfiguration {HasHeaderRecord = false}; _csv = new CsvReader(_reader, csvConfiguration); } public LeafInput Parse() { // First 10 lines var leafInput = ParseLeafInput(); leafInput.FileName = _csvFile.Name; // Next 3 (Header, Units, and Values) leafInput.Site = ParseLeafInputSite(); // Next 3 (Header, Units, and Values) leafInput.Photosynthetic = ParseLeafInputPhotosynthetic(); // Remaining lines (Header, Units, and Data) leafInput.Data = ParseLeafInputData(); return leafInput; } private LeafInput ParseLeafInput() { var items = new List(); for (var i = 0; i < 10; i++) { if (!_csv.Read()) throw new ParseException("Could not read line number " + _csv.Row); string field; if (!_csv.TryGetField(0, out field)) throw new ParseException("Could not read first field on line number " + _csv.Row); items.Add(field); } return ParsedObjectFactory.Create(items.ToArray()); } private string[] GetNextCsvRowValues() { // get values from row if (!_csv.Read()) return null; // put all the values from this row into an array var values = new List(); var index = 0; string value; while (_csv.TryGetField(index, out value)) { values.Add(value); index++; } return values.ToArray(); } private LeafInputSite ParseLeafInputSite() { var titles = GetNextCsvRowValues(); if (titles == null) throw new ParseException("Could not read site header row on line number " + _csv.Row); var units = GetNextCsvRowValues(); if (units == null) throw new ParseException("Could not read site units row on line number " + _csv.Row); var values = GetNextCsvRowValues(); if (values == null) throw new ParseException("Could not read site value row on line number " + _csv.Row); var items = new List>(); for (var i = 0; i < titles.Length && i < values.Length; i++) { var item = Tuple.Create(titles[i], values[i]); items.Add(item); } return ParsedObjectFactory.Create(items.ToArray()); } private LeafInputPhotosynthetic ParseLeafInputPhotosynthetic() { var titles = GetNextCsvRowValues(); if (titles == null) throw new ParseException("Could not read photosynthetic header row on line number " + _csv.Row); var units = GetNextCsvRowValues(); if (units == null) throw new ParseException("Could not read photosynthetic units row on line number " + _csv.Row); var values = GetNextCsvRowValues(); if (values == null) throw new ParseException("Could not read photosynthetic value row on line number " + _csv.Row); var items = new List>(); for (var i = 0; i < titles.Length && i < values.Length; i++) { var item = Tuple.Create(titles[i], values[i]); items.Add(item); } return ParsedObjectFactory.Create(items.ToArray()); } private LeafInputData[] ParseLeafInputData() { var titles = GetNextCsvRowValues(); if (titles == null) throw new ParseException("Could not read data header row on line number " + _csv.Row); var units = GetNextCsvRowValues(); if (units == null) throw new ParseException("Could not read data units row on line number " + _csv.Row); var valueArrays = new List(); while (true) { var values = GetNextCsvRowValues(); if (values == null) break; valueArrays.Add(values); } return ParsedObjectFactory.Create(titles, valueArrays.ToArray()); } public void Dispose() { _reader.Dispose(); } public static void ExportCsv(string filename, IEnumerable leafInputs) { using (var textWriter = new StreamWriter(filename)) { var csv = new CsvWriter(textWriter); csv.WriteRecords(leafInputs); } } } }