private static void ReadCsvAsStrings(TextReader reader, out NamedList <string>[] columns, out DataAdaptor[] headers) { Debug.Assert(reader != null); // Get the column names from the first line. string firstline = reader.ReadLine(); if (firstline == null) { columns = null; headers = null; return; } List <string> names = CsvHelper.ReadCells(firstline); int count = names.Count; // Put the columns into lists of strings, and as we do so, maintain the collection of // types it can be parsed into, and whether any entries are null. columns = new NamedList <string> [names.Count]; headers = new DataAdaptor[names.Count]; for (int columnIndex = 0; columnIndex < columns.Length; columnIndex++) { columns[columnIndex] = new NamedList <string>(names[columnIndex]); headers[columnIndex] = new DataAdaptor(); } while (true) { string line = reader.ReadLine(); if (line == null) { break; } List <string> cells = CsvHelper.ReadCells(line); if (cells.Count != count) { throw new FormatException(); } for (int columnIndex = 0; columnIndex < count; columnIndex++) { string cell = cells[columnIndex]; if (String.IsNullOrEmpty(cell)) { headers[columnIndex].IsNullable = true; columns[columnIndex].Add(null); } else { DataAdaptor header = headers[columnIndex]; header.TryParse(cell); columns[columnIndex].Add(cell); } } } }
/// <summary> /// Creates a new frame table from a file of comma-separated values. /// </summary> /// <param name="reader">A reader positioned at the beginning of the file.</param> /// <returns>A new data frame with data from the file.</returns> /// <remarks> /// <para>The column names are taken from the first line of the file.</para> /// <para>The storage type of each column is inferred from the types of objects /// encountered are the frame table is constructed.</para> /// </remarks> public static FrameTable FromCsv(TextReader reader) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } NamedList <string>[] textColumns; DataAdaptor[] headers; ReadCsvAsStrings(reader, out textColumns, out headers); NamedList[] columns = new NamedList[headers.Length]; for (int columnIndex = 0; columnIndex < columns.Length; columnIndex++) { DataAdaptor header = headers[columnIndex]; if (header.TypeCandidates.Count == 0) { columns[columnIndex] = textColumns[columnIndex]; } else { TypeParser adaptor = header.TypeCandidates.First.Value; NamedList column = adaptor.CreateStorage(textColumns[columnIndex].Name, header.IsNullable); foreach (string textValue in textColumns[columnIndex]) { if (textValue == null) { column.AddItem(null); } else { object value = adaptor.Parse(textValue); column.AddItem(value); } } columns[columnIndex] = column; } } FrameTable frame = new FrameTable(columns); return(frame); }
private static void ReadCsvAsStrings(TextReader reader, out DataList <string>[] columns, out DataAdaptor[] headers) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } string firstline = reader.ReadLine(); if (firstline == null) { columns = null; headers = null; return; } List <string> names = CsvHelper.ReadCells(firstline); int count = names.Count; columns = new DataList <string> [names.Count]; headers = new DataAdaptor[names.Count]; for (int columnIndex = 0; columnIndex < columns.Length; columnIndex++) { columns[columnIndex] = new DataList <string>(names[columnIndex]); headers[columnIndex] = new DataAdaptor(); } while (true) { string line = reader.ReadLine(); if (line == null) { break; } List <string> cells = CsvHelper.ReadCells(line); if (cells.Count != count) { throw new FormatException(); } for (int columnIndex = 0; columnIndex < count; columnIndex++) { string cell = cells[columnIndex]; if (String.IsNullOrEmpty(cell)) { headers[columnIndex].IsNullable = true; columns[columnIndex].Add(null); } else { DataAdaptor header = headers[columnIndex]; LinkedListNode <TypeAdaptor> adaptorNode = header.TypeCandidates.First; while (adaptorNode != null) { if (!adaptorNode.Value.IsParsable(cell)) { header.TypeCandidates.Remove(adaptorNode); } adaptorNode = adaptorNode.Next; } columns[columnIndex].Add(cell); } } } }