Skip to content

Instantly share code, notes, and snippets.

@tomtheisen
Last active May 1, 2020 01:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomtheisen/cf6afee1210b9625181bb3c23ea0f204 to your computer and use it in GitHub Desktop.
Save tomtheisen/cf6afee1210b9625181bb3c23ea0f204 to your computer and use it in GitHub Desktop.
List<List<string>> ReadCsv(string fileName) {
using var reader = new StreamReader(File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
return ReadCsv(reader);
}
List<List<string>> ReadCsv(TextReader reader) {
var result = new List<List<string>>();
var currentRow = new List<string>();
var currentCell = new StringBuilder();
int c;
void ReadNewLine() {
if (reader.Read() != '\n') throw new FormatException("Found carriage return without following linefeed");
currentRow.Add(currentCell.ToString());
result.Add(currentRow);
currentCell.Clear();
currentRow = new List<string>();
}
void AddCell() {
currentRow.Add(currentCell.ToString());
currentCell.Clear();
}
void AddRow() {
currentRow.Add(currentCell.ToString());
result.Add(currentRow);
}
Start: switch (c = reader.Read()) {
case '\r':
ReadNewLine();
goto Start;
case '"':
goto QuotedCell;
case int _ when c < 0:
if (currentRow.Count > 0) result.Add(currentRow);
return result;
default:
currentCell.Append((char)c);
goto RawCell;
}
QuotedCell: switch (c = reader.Read()) {
case '"':
goto EndQuote;
case int _ when c < 0:
throw new FormatException($"Unterminated quoted value encountered in record {result.Count + 1}");
default:
currentCell.Append((char)c);
goto QuotedCell;
}
EndQuote: switch (c = reader.Read()) {
case '\r':
ReadNewLine();
goto Start;
case ',':
AddCell();
goto Start;
case '"':
currentCell.Append('"');
goto QuotedCell;
case int _ when c < 0:
AddCell();
return result;
default:
throw new FormatException($"Unexpected character following trailing quote '{(char)c}'");
}
RawCell: switch (c = reader.Read()) {
case '"':
throw new FormatException("Encountered quote character (\") in unquoted value");
case ',':
AddCell();
goto Start;
case '\r':
ReadNewLine();
goto Start;
case int _ when c < 0:
AddRow();
return result;
default:
currentCell.Append((char)c);
goto RawCell;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment