namespace SS { using System; using System.IO; using System.Text; using System.Text.RegularExpressions; using System.Collections.Generic; /// /// CSV Reader. this class accepts a CSV file generated by Microsoft Excel. /// public class CSVReader { // flag for processing a CSV private enum ParsingMode { // default(treat as null) None, // processing a character which is out of quotes OutQuote, // processing a character which is in quotes InQuote } /// /// Parses the CSV string. /// /// a two-dimensional array. first index indicates the row. second index indicates the column. /// raw CSV contents as string public List> ParseCSV(string src) { var rows = new List>(); var cols = new List(); #pragma warning disable XS0001 // Find APIs marked as TODO in Mono var buffer = new StringBuilder(); #pragma warning restore XS0001 // Find APIs marked as TODO in Mono ParsingMode mode = ParsingMode.OutQuote; bool requireTrimLineHead = false; var isBlank = new Regex(@"\s"); int len = src.Length; for (int i = 0; i < len; ++i) { char c = src[i]; // remove whilespace at beginning of line if (requireTrimLineHead) { if (isBlank.IsMatch(c.ToString())) { continue; } requireTrimLineHead = false; } // finalize when c is the last character if ((i + 1) == len) { // final char switch (mode) { case ParsingMode.InQuote: if (c == '"') { // ignore } else { // if close quote is missing buffer.Append(c); } cols.Add(buffer.ToString()); rows.Add(cols); return rows; case ParsingMode.OutQuote: if (c == ',') { // if the final character is comma, add an empty cell // next col cols.Add(buffer.ToString()); cols.Add(string.Empty); rows.Add(cols); return rows; } if (cols.Count == 0) { // if the final line is empty, ignore it. if (string.Empty.Equals(c.ToString().Trim())) { return rows; } } buffer.Append(c); cols.Add(buffer.ToString()); rows.Add(cols); return rows; } } // the next character char n = src[i + 1]; switch (mode) { case ParsingMode.OutQuote: // out quote if (c == '"') { // to in-quote mode = ParsingMode.InQuote; continue; } else if (c == ',') { // next cell cols.Add(buffer.ToString()); buffer.Remove(0, buffer.Length); } else if (c == '\r' && n == '\n') { // new line(CR+LF) cols.Add(buffer.ToString()); rows.Add(cols); cols = new List(); buffer.Remove(0, buffer.Length); ++i; // skip next code requireTrimLineHead = true; } else if (c == '\n' || c == '\r') { // new line cols.Add(buffer.ToString()); rows.Add(cols); cols = new List(); buffer.Remove(0, buffer.Length); requireTrimLineHead = true; } else { // get one char buffer.Append(c); } break; case ParsingMode.InQuote: // in quote if (c == '"' && n != '"') { // to out-quote mode = ParsingMode.OutQuote; } else if (c == '"' && n == '"') { // get " buffer.Append('"'); ++i; } else { // get one char buffer.Append(c); } break; } } return rows; } } }