Reading and writing CSV files¶
Introduction
Comma-separated values (abbreviated as CSV) is a file format based on text files used for importing and exporting (for example from spreadsheets or databases) of a data table.
In this format, each row of the table (or database record) is normally represented by a line of text, which in turn is divided into fields (the individual columns) separated by a special separator character, each of which represents a value.
To facilitate the reading and generation of files in CSV format, the CSVFileReader and CSVFileWriter C# classes are available.
CSVFileReader
Documentation CSVFileReader.
using System;
using System.Text;
using System.IO;
using System.Collections.Generic;
private class CSVFileReader : IDisposable
{
public char FieldDelimiter { get; set; } = ',';
public char QuoteChar { get; set; } = '"';
public bool IgnoreMalformedLines { get; set; } = false;
public CSVFileReader(string filePath, Encoding encoding)
{
streamReader = new StreamReader(filePath, encoding);
}
public CSVFileReader(string filePath)
{
streamReader = new StreamReader(filePath, Encoding.UTF8);
}
public CSVFileReader(System.IO.StreamReader streamReader)
{
this.streamReader = streamReader;
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
streamReader.Dispose();
disposed = true;
}
public bool EndOfFile()
{
return streamReader.EndOfStream;
}
public List<string> ReadLine()
{
if (EndOfFile())
return null;
var line = streamReader.ReadLine();
return ParseLine(line);
}
public List<List<string>> ReadAll()
{
var result = new List<List<string>>();
while (!EndOfFile())
result.Add(ReadLine());
return result;
}
private List<string> ParseLine(string line)
{
var fields = new List<string>();
var buffer = new StringBuilder("");
var fieldParsing = false;
int i = 0;
while (i < line.Length)
{
if (!fieldParsing)
{
if (IsWhiteSpace(line, i))
{
++i;
continue;
}
if (i == 0)
{
// A line must begin with the quotation mark
if (!IsQuoteChar(line, i))
{
if (IgnoreMalformedLines)
return null;
else
throw new FormatException("Expected quotation marks at " + i);
}
fieldParsing = true;
}
else
{
if (IsQuoteChar(line, i))
fieldParsing = true;
else if (!IsFieldDelimiter(line, i))
{
if (IgnoreMalformedLines)
return null;
else
throw new FormatException("Wrong field delimiter at " + i);
}
}
++i;
}
else
{
if (IsEscapedQuoteChar(line, i))
{
i += 2;
buffer.Append(QuoteChar);
}
else if (IsQuoteChar(line, i))
{
fields.Add(buffer.ToString());
buffer.Clear();
fieldParsing = false;
++i;
}
else
{
buffer.Append(line[i]);
++i;
}
}
}
return fields;
}
private bool IsEscapedQuoteChar(string line, int i)
{
return line[i] == QuoteChar && i != line.Length - 1 && line[i + 1] == QuoteChar;
}
private bool IsQuoteChar(string line, int i)
{
return line[i] == QuoteChar;
}
private bool IsFieldDelimiter(string line, int i)
{
return line[i] == FieldDelimiter;
}
private bool IsWhiteSpace(string line, int i)
{
return Char.IsWhiteSpace(line[i]);
}
bool disposed = false;
StreamReader streamReader;
}
CSVFileWriter
Documentation CSVFileWriter.
using System.Text;
using System.IO;
private class CSVFileWriter : IDisposable
{
public char FieldDelimiter { get; set; } = ',';
public char QuoteChar { get; set; } = '"';
public CSVFileWriter(string filePath)
{
streamWriter = new StreamWriter(filePath, false, Encoding.UTF8);
}
public CSVFileWriter(string filePath, Encoding encoding)
{
streamWriter = new StreamWriter(filePath, false, encoding);
}
public CSVFileWriter(System.IO.StreamWriter streamReader)
{
this.streamWriter = streamReader;
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
streamWriter.Dispose();
disposed = true;
}
public void WriteLine(string[] fields)
{
var stringBuilder = new StringBuilder();
for (var i = 0; i < fields.Length; ++i)
{
stringBuilder.AppendFormat("{0}{1}{0}", QuoteChar, EscapeField(fields[i]), QuoteChar);
if (i != fields.Length - 1)
stringBuilder.Append(FieldDelimiter);
}
streamWriter.WriteLine(stringBuilder.ToString());
streamWriter.Flush();
}
private string EscapeField(string field)
{
var quoteCharString = QuoteChar.ToString();
return field.Replace(quoteCharString, quoteCharString + quoteCharString);
}
bool disposed = false;
StreamWriter streamWriter;
}