diff --git a/ICD.Common.Utils/Csv/CsvWriter.cs b/ICD.Common.Utils/Csv/CsvWriter.cs
new file mode 100644
index 0000000..0911129
--- /dev/null
+++ b/ICD.Common.Utils/Csv/CsvWriter.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Linq;
+using ICD.Common.Properties;
+using ICD.Common.Utils.IO;
+
+namespace ICD.Common.Utils.Csv
+{
+ public sealed class CsvWriter : IDisposable
+ {
+ private const string QUOTATION_MARK = "\"";
+ private const string DOUBLE_QUOTE_MARK = "\"\"";
+
+ private readonly IcdTextWriter m_Writer;
+
+ private readonly string m_Seperator;
+ private readonly string m_LineTerminator;
+ private readonly bool m_AlwaysEscape;
+
+ private bool m_NewLine;
+
+ ///
+ /// Constructor.
+ ///
+ public CsvWriter(IcdTextWriter writer, bool spaceAfterComma, bool alwaysEscape, string newline, params string[] header)
+ {
+ m_NewLine = true;
+ m_Writer = writer;
+ m_Seperator = spaceAfterComma ? ", " : ",";
+ m_AlwaysEscape = alwaysEscape;
+ m_LineTerminator = newline;
+
+ if(header.Any())
+ AppendRow(header);
+ }
+
+ ~CsvWriter()
+ {
+ Dispose();
+ }
+
+ ///
+ /// Calls ToString() for each item and adds the row to the builder.
+ ///
+ ///
+ [PublicAPI]
+ public void AppendRow(params object[] row)
+ {
+ foreach (object value in row)
+ AppendValue(value);
+ AppendNewline();
+ }
+
+ ///
+ /// Adds the row to the builder.
+ ///
+ ///
+ [PublicAPI]
+ public void AppendRow(params string[] row)
+ {
+ foreach (string value in row)
+ AppendValue(value);
+ AppendNewline();
+ }
+
+ ///
+ /// Calls ToString() on the item and adds it to the builder.
+ ///
+ ///
+ [PublicAPI]
+ public void AppendValue(object value)
+ {
+ AppendValue(string.Format("{0}", value));
+ }
+
+ ///
+ /// Adds a value to the builder.
+ ///
+ ///
+ [PublicAPI]
+ public void AppendValue(string value)
+ {
+ if (!m_NewLine)
+ m_Writer.WrappedTextWriter.Write(m_Seperator);
+
+ if (m_AlwaysEscape || value.Contains(","))
+ {
+ value = value.Replace(QUOTATION_MARK, DOUBLE_QUOTE_MARK);
+
+ // Append the value, surrounded by quotes
+ m_Writer.WrappedTextWriter.Write(QUOTATION_MARK);
+ m_Writer.WrappedTextWriter.Write(value);
+ m_Writer.WrappedTextWriter.Write(QUOTATION_MARK);
+ }
+ else
+ {
+ m_Writer.WrappedTextWriter.Write(value);
+ }
+
+ m_NewLine = false;
+ }
+
+ ///
+ /// Adds a New Line To the Builder
+ ///
+ [PublicAPI]
+ public void AppendNewline()
+ {
+ m_Writer.WrappedTextWriter.Write(m_LineTerminator);
+
+ m_NewLine = true;
+ }
+
+ public void Dispose()
+ {
+ m_Writer.Dispose();
+ }
+
+ ///
+ /// Instantiates a new CsvWriter with the properties given in the CsvWriterSettings.
+ ///
+ ///
+ ///
+ ///
+ ///
+ [PublicAPI]
+ public static CsvWriter Create(IcdTextWriter writer, CsvWriterSettings settings, params string[] header)
+ {
+ return new CsvWriter(writer,
+ settings.InsertSpaceAfterComma,
+ settings.AlwaysEscapeEveryValue,
+ settings.NewLineSequence,
+ header);
+ }
+ }
+}
\ No newline at end of file
diff --git a/ICD.Common.Utils/Csv/CsvWriterSettings.cs b/ICD.Common.Utils/Csv/CsvWriterSettings.cs
new file mode 100644
index 0000000..249abdf
--- /dev/null
+++ b/ICD.Common.Utils/Csv/CsvWriterSettings.cs
@@ -0,0 +1,46 @@
+using ICD.Common.Properties;
+
+namespace ICD.Common.Utils.Csv
+{
+ public sealed class CsvWriterSettings
+ {
+ private bool m_InsertSpaceAfterComma = true;
+ private bool m_AlwaysEscapeEveryValue = true;
+ private string m_NewLineSequence = IcdEnvironment.NewLine;
+
+ ///
+ /// Gets/Sets whether to insert a space between elements, after the comma
+ /// Defaults to true.
+ ///
+ [PublicAPI]
+ public bool InsertSpaceAfterComma
+ {
+ get { return m_InsertSpaceAfterComma; }
+ set { m_InsertSpaceAfterComma = value; }
+ }
+
+ ///
+ /// Gets/Sets whether to always escape the values.
+ /// If true, values are recorded surrounded by quotes, regardless of if they contain a comma or not. Quotes are escaped.
+ /// If false, values are recorded as the value without quotes, unless escaping is required.
+ /// Defaults to true.
+ ///
+ [PublicAPI]
+ public bool AlwaysEscapeEveryValue
+ {
+ get { return m_AlwaysEscapeEveryValue; }
+ set { m_AlwaysEscapeEveryValue = value; }
+ }
+
+ ///
+ /// Gets/Sets the newline character or characters to deliniate records.
+ /// Defaults to System.NewLine.
+ ///
+ [PublicAPI]
+ public string NewLineSequence
+ {
+ get { return m_NewLineSequence; }
+ set { m_NewLineSequence = value; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj b/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj
index b663b60..811faf7 100644
--- a/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj
+++ b/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj
@@ -79,6 +79,8 @@
+
+
@@ -92,6 +94,7 @@
+
diff --git a/ICD.Common.Utils/IO/IcdFile.cs b/ICD.Common.Utils/IO/IcdFile.cs
index 0b90670..0dcd728 100644
--- a/ICD.Common.Utils/IO/IcdFile.cs
+++ b/ICD.Common.Utils/IO/IcdFile.cs
@@ -89,5 +89,11 @@ namespace ICD.Common.Utils.IO
{
return new IcdFileStream(File.Create(path));
}
+
+ [PublicAPI]
+ public static IcdStreamWriter AppendText(string path)
+ {
+ return new IcdStreamWriter(File.AppendText(path));
+ }
}
}
diff --git a/ICD.Common.Utils/IO/IcdStreamWriter.cs b/ICD.Common.Utils/IO/IcdStreamWriter.cs
new file mode 100644
index 0000000..4d5604a
--- /dev/null
+++ b/ICD.Common.Utils/IO/IcdStreamWriter.cs
@@ -0,0 +1,22 @@
+using System;
+#if SIMPLSHARP
+using Crestron.SimplSharp.CrestronIO;
+#elif STANDARD
+using System.IO;
+#endif
+
+namespace ICD.Common.Utils.IO
+{
+ public sealed class IcdStreamWriter : IcdTextWriter
+ {
+ public StreamWriter WrappedStreamWriter { get { return WrappedTextWriter as StreamWriter; } }
+
+ ///
+ /// Constructor.
+ ///
+ ///
+ public IcdStreamWriter(StreamWriter baseStreamWriter) : base(baseStreamWriter)
+ {
+ }
+ }
+}
\ No newline at end of file