Last active
January 30, 2018 23:10
-
-
Save sbrl/281eb4b26870c94523aa to your computer and use it in GitHub Desktop.
[CSVWriter.cs] A simple, flexible CSV writer for C#. Modeled on the StreamWriter class. #microlibrary
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
/****************************************************************************** | |
* CSVWriter | |
****************************************************************************** | |
* Version 0.8 | |
* Author: Starbeamrainbowlabs <feedback at starbeamrainbowlabs dot com> | |
* | |
* An easy way to generate CSV files. Please allow this comment to remain | |
* intact. | |
****************************************************************************** | |
* Changelog | |
****************************************************************************** | |
* 22nd December 2015: | |
* - Uploaded to GitHub gist. | |
* | |
*/ | |
using System; | |
using System.Collections.Generic; | |
using System.Text; | |
using System.IO; | |
namespace CSVHandler | |
{ | |
/// <summary> | |
/// A class that aids the writing of a (hopefully) fully valid CSV file. | |
/// </summary> | |
public class CSVWriter | |
{ | |
/// <summary> | |
/// The destination stream to which we will be writing the csv. | |
/// </summary> | |
private StreamWriter destination; | |
/// <summary> | |
/// Whether the underlying filestream is open or closed. True if the stream is open, false if closed. | |
/// </summary> | |
public bool IsOpen | |
{ | |
get | |
{ | |
return destination.BaseStream != null; | |
} | |
} | |
/// <summary> | |
/// Whether the headers have been writteen yet or not. | |
/// </summary> | |
private bool headersWritten = false; | |
/// <summary> | |
/// Whether the headers have been written. | |
/// Note that attempting to write the headers again when they have already been written results in an exception been thrown. | |
/// </summary> | |
public bool HeadersWritten | |
{ | |
get | |
{ | |
return headersWritten; | |
} | |
} | |
/// <summary> | |
/// The number of fields that were specified when writing the headers. | |
/// </summary> | |
private int fieldCount; | |
/// <summary> | |
/// The number of fields declared when writing the headers. Records written to the CSV writer must have this number of fields, even if they are just empty strings. | |
/// </summary> | |
public int FieldCount | |
{ | |
get | |
{ | |
return fieldCount; | |
} | |
} | |
/// <summary> | |
/// The number of records that have been written to the output stream so far. | |
/// </summary> | |
private int recordsWritten = 0; | |
/// <summary> | |
/// The number of records written to the output stream so far. Note that this doesn't include the header line. | |
/// </summary> | |
public int RecordsWritten | |
{ | |
get | |
{ | |
return recordsWritten; | |
} | |
} | |
/// <summary> | |
/// Creates a new CSV writer that will write out to the given filename. | |
/// </summary> | |
/// <param name="filename">The filename to write the csv to.</param> | |
public CSVWriter(string filename) : this(new StreamWriter(filename)) | |
{ | |
} | |
/// <summary> | |
/// Creates a new CSV writer that will write to the given StreamWriter. | |
/// </summary> | |
/// <param name="inDestination">The StreamWriter to write the csv to.</param> | |
public CSVWriter(StreamWriter inDestination) | |
{ | |
destination = inDestination; | |
} | |
/// <summary> | |
/// Encapsulates a given string in quotes if it contains a comma. | |
/// Rather useful when preparing cell data for writing. | |
/// </summary> | |
/// <param name="cellData">The string to check.</param> | |
/// <returns>The properly escaped string.</returns> | |
private string escapeCellData(string cellData) | |
{ | |
if (cellData.Contains(",")) | |
return String.Format("\"{0}\"", cellData); | |
else | |
return cellData; | |
} | |
/// <summary> | |
/// Writes the header contained in the given array to the file. | |
/// </summary> | |
/// <param name="inHeaders">The headers to write to the csv file.</param> | |
public void WriteHeader(string[] inHeaders) | |
{ | |
// Blow up if we try to write the headersmeor than once. | |
if(headersWritten) | |
throw new InvalidOperationException("You cannot write the CSV headers more than once."); | |
// Save the number of headers for later | |
fieldCount = inHeaders.Length; | |
// Loop over each header and prepare it for writing. This encapsulates the header in quotes if it contians a comma. | |
string[] preparedHeaders = new string[inHeaders.Length]; | |
for(int i = 0; i < inHeaders.Length; i++) | |
{ | |
preparedHeaders[i] = escapeCellData(inHeaders[i]); | |
} | |
destination.WriteLine(String.Join(",", preparedHeaders)); | |
headersWritten = true; | |
} | |
/// <summary> | |
/// Writes a new record to the csv file. | |
/// Note that the number of fields in the data provided must the equal to that declared when writing the header. | |
/// </summary> | |
/// <param name="data">An array of records to write out.</param> | |
public void WriteRecord(string[] data) | |
{ | |
if(data.Length != FieldCount) | |
throw new FormatException(String.Format("Data does not have the expected number of fields. Expected: {0}, Actual: {1}", data.Length, FieldCount)); | |
string[] preparedData = new string[data.Length]; | |
for(int i = 0; i < data.Length; i++) | |
{ | |
preparedData[i] = escapeCellData(data[i]); | |
} | |
destination.WriteLine(String.Join(",", preparedData)); | |
recordsWritten++; | |
} | |
/// <summary> | |
/// Closes the underlying StreamWriter. | |
/// Don't attempt to write to the CSV writer after you've closed the file, as this will throw an exception! | |
/// </summary> | |
public void Close() | |
{ | |
destination.Close(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment