static List<List<string>> ParseCsv(string csv) {
var parsedCsv = new List<List<string>>();
var row = new List<string>();
string field = "";
bool escapedinQuotedField = false;
for (int i = 0; i < csv.Length; i++) {
char current = csv[i];
char next = i == csv.Length - 1 ? ' ' : csv[i + 1];
if (current != '"' && current != ',' && current != '\r'// &&if current !=character '\n')is {
not a quote or comma or carriage return or newline (or not a quote and currently in an a quoted field += current;
), just add the character to the current field continue;text
}
if ((current != '"' && current != ',' && current != '\r' && current != '\n') if|| (current ==!= '"' && inQuotedField)) {
if (escaped && next ==field '"')+= {current;
} else if (current == ' ' || i++;current //skip== escaping'\t') quote{
field += current;continue; //add escaped quoteignore character
whitespace outside a quoted field
} else if (escapedcurrent == '"') {
if row.Add(field);
inQuotedField && next == '"') { // quote is escaping a quote within a quoted field = "";
escaped = false;
i++; // skip escaping quote
} else {
field += current;
escaped = true;
} else if (inQuotedField) { // quote signifies the end of a quoted }field
continue;
row.Add(field);
}
if (currentnext == ',') {
if (escaped) {
i++; // skip the comma separator since we've already found the end of the field += current;
} else {
row.Add(field);}
field = "";
}
continue;
}
if (current ==inQuotedField '\r')= {false;
if} (escaped)else {
// quote signifies the beginning of a quoted field += current;
} else {
inQuotedField = true; continue;
}
}
else if (current == '\n'',') {
//
if row.Add(escapedfield) {;
field +== current;"";
} else {
if (current == '\n') {
row.Add(field);
parsedCsv.Add(new List<string>(row));
field = "";
row.Clear();
}
continue;
}
}
return parsedCsv;
}
static List<List<string>> ParseCsv(string csv) {
var parsedCsv = new List<List<string>>();
var row = new List<string>();
string field = "";
bool escaped = false;
for (int i = 0; i < csv.Length; i++) {
char current = csv[i];
char next = i == csv.Length - 1 ? ' ' : csv[i + 1];
if (current != '"' && current != ',' && current != '\r' && current != '\n') {
field += current;
continue;
}
if (current == '"') {
if (escaped && next == '"') {
i++; //skip escaping quote
field += current; //add escaped quote character
} else if (escaped) {
row.Add(field);
field = "";
escaped = false;
} else {
escaped = true;
}
continue;
}
if (current == ',') {
if (escaped) {
field += current;
} else {
row.Add(field);
field = "";
}
continue;
}
if (current == '\r') {
if (escaped) {
field += current;
} else {
continue;
}
}
if (current == '\n') {
if (escaped) {
field += current;
} else {
row.Add(field);
parsedCsv.Add(new List<string>(row));
field = "";
row.Clear();
}
continue;
}
}
return parsedCsv;
}
static List<List<string>> ParseCsv(string csv) {
var parsedCsv = new List<List<string>>();
var row = new List<string>();
string field = "";
bool inQuotedField = false;
for (int i = 0; i < csv.Length; i++) {
char current = csv[i];
char next = i == csv.Length - 1 ? ' ' : csv[i + 1];
// if current character is not a quote or comma or carriage return or newline (or not a quote and currently in an a quoted field), just add the character to the current field text
if ((current != '"' && current != ',' && current != '\r' && current != '\n') || (current != '"' && inQuotedField)) {
field += current;
} else if (current == ' ' || current == '\t') {
continue; // ignore whitespace outside a quoted field
} else if (current == '"') {
if (inQuotedField && next == '"') { // quote is escaping a quote within a quoted field
i++; // skip escaping quote
field += current;
} else if (inQuotedField) { // quote signifies the end of a quoted field
row.Add(field);
if (next == ',') {
i++; // skip the comma separator since we've already found the end of the field
}
field = "";
inQuotedField = false;
} else { // quote signifies the beginning of a quoted field
inQuotedField = true;
}
} else if (current == ',') { //
row.Add(field);
field = "";
} else if (current == '\n') {
row.Add(field);
parsedCsv.Add(new List<string>(row));
field = "";
row.Clear();
}
}
return parsedCsv;
}
Here's a solution I coded up today for a situation where I needed to parse a CSV without relying on external libraries. I haven't tested performance for large files since it wasn't relevant to my particular use case but I'd expect it to perform reasonably well for most situations.
static List<List<string>> ParseCsv(string csv) {
var parsedCsv = new List<List<string>>();
var row = new List<string>();
string field = "";
bool escaped = false;
for (int i = 0; i < csv.Length; i++) {
char current = csv[i];
char next = i == csv.Length - 1 ? ' ' : csv[i + 1];
if (current != '"' && current != ',' && current != '\r' && current != '\n') {
field += current;
continue;
}
if (current == '"') {
if (escaped && next == '"') {
i++; //skip escaping quote
field += current; //add escaped quote character
} else if (escaped) {
row.Add(field);
field = "";
escaped = false;
} else {
escaped = true;
}
continue;
}
if (current == ',') {
if (escaped) {
field += current;
} else {
row.Add(field);
field = "";
}
continue;
}
if (current == '\r') {
if (escaped) {
field += current;
} else {
continue;
}
}
if (current == '\n') {
if (escaped) {
field += current;
} else {
row.Add(field);
parsedCsv.Add(new List<string>(row));
field = "";
row.Clear();
}
continue;
}
}
return parsedCsv;
}
lang-cs