From 2ff70733858e31470a58a3ea4cdfe780b7641a65 Mon Sep 17 00:00:00 2001 From: Jack Kanarish Date: Tue, 28 Aug 2018 10:52:12 -0400 Subject: [PATCH] feat: add CSV Writer --- ICD.Common.Utils/Csv/CsvWriter.cs | 135 ++++++++++++++++++ ICD.Common.Utils/Csv/CsvWriterSettings.cs | 46 ++++++ .../ICD.Common.Utils_SimplSharp.csproj | 3 + ICD.Common.Utils/IO/IcdFile.cs | 6 + ICD.Common.Utils/IO/IcdStreamWriter.cs | 22 +++ 5 files changed, 212 insertions(+) create mode 100644 ICD.Common.Utils/Csv/CsvWriter.cs create mode 100644 ICD.Common.Utils/Csv/CsvWriterSettings.cs create mode 100644 ICD.Common.Utils/IO/IcdStreamWriter.cs 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