Last active
May 1, 2020 01:27
-
-
Save tomtheisen/cf6afee1210b9625181bb3c23ea0f204 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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