How to parse CSV files in C#

johna by | February 16, 2020 | C#

There's various ways to parse CSV files. Some don't always work well and some do work well but are bigger than you might want.

This is a simple C# class that can read a CSV file line by line and provide the row's column values in a List<string>.

It can handle values with or without delimiters (quotation marks), and carriage returns/line feeds within delimited values.

Usage example:

CsvReader file = new CsvReader(Server.MapPath("file.csv"));

while (!file.EndOfFile)
{
List<string> row = file.Read();

if (row != null)
{
//do something with each cell, eg. row[0]
}
}

file.Close();


The class:

public class CsvReader
{
private StreamReader _reader;

private bool _endOfFile;

public bool EndOfFile
{
get
{
return this._endOfFile;
}
}

public CsvReader(string file)
{
this._endOfFile = false;
this._reader = new StreamReader(file);
}

public List<string> Read()
{
if (this._endOfFile)
{
return null;
}

string line = this._reader.ReadLine();

if (line == null)
{
this._endOfFile = true;

return null;
}

List<string> result = new List<string>();

bool inDelimiters = false;

int startPos = 0;

int pos = 0;

while (pos <= line.Length)
{
string chr = (pos < line.Length ? line.Substring(pos, 1) : null);

if (chr == """ && !inDelimiters && pos == startPos)
{
inDelimiters = true;
}
else if (chr == """ && inDelimiters)
{
if (pos == line.Length - 1)
{
result.Add(line.Substring(startPos + 1, pos - (startPos + 1)).Replace("""", """));

break;
}
else if (line.Substring(pos + 1, 1) == ",")
{
result.Add(line.Substring(startPos + 1, pos - (startPos + 1)).Replace("""", """));

pos++;

startPos = pos + 1;

inDelimiters = false;
}
else if (line.Substring(pos + 1, 1) == """)
{
pos++;

if (pos == (line.Length - 1))
{
string nextLine = this._reader.ReadLine();

if (nextLine == null)
{
throw new Exception("CSV file is invalid");
}

line += "\n" + nextLine;
}
}
}
else if (chr == "," && !inDelimiters)
{
result.Add(line.Substring(startPos, pos - startPos));

startPos = pos + 1;

if (startPos == line.Length)
{
result.Add(string.Empty);
}
}
else if (pos == (line.Length - 1) && inDelimiters)
{
string nextLine = this._reader.ReadLine();

if (nextLine == null)
{
throw new Exception("CSV file is invalid");
}

line += "\n" + nextLine;
}
else if (pos == line.Length - 1)
{
result.Add(line.Substring(startPos, (pos + 1) - startPos));

break;
}

pos++;
}

return result;
}

public void Close()
{
if (this._reader != null)
{
this._reader.Close();
this._reader = null;
}
}

~CsvReader()
{
this.Close();
}
}

Related Posts

C# Web Development

Search result highlighting and truncation in C#

by johna | February 3, 2016
Isn't it nice how search engines show a brief section of content with your search terms highlighted in search results?

Comments

There are no comments yet. Be the first to leave a comment!

Leave a Comment

About

...random postings about web development and programming, Internet, computers and electronics topics.

I recommend ASPnix for web hosting and Crazy Domains for domain registration.

Subscribe

Get the latest posts delivered to your inbox.