/****************************************************************************** | |
* 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