From c32bfc35f9048fa1f1c9fd3d60d1b9efeb02519e Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Sat, 13 Jun 2020 21:24:47 -0700 Subject: [PATCH] Add SeparatedValueWriter --- .../Tools/SeparatedValueWriter.cs | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 SabreTools.Library/Tools/SeparatedValueWriter.cs diff --git a/SabreTools.Library/Tools/SeparatedValueWriter.cs b/SabreTools.Library/Tools/SeparatedValueWriter.cs new file mode 100644 index 00000000..a7a9f475 --- /dev/null +++ b/SabreTools.Library/Tools/SeparatedValueWriter.cs @@ -0,0 +1,143 @@ +using System; +using System.IO; +using System.Text; + +namespace SabreTools.Library.Tools +{ + public class SeparatedValueWriter : IDisposable + { + /// + /// Internal stream writer for outputting + /// + private StreamWriter sw; + + /// + /// Internal value if we've written a header before + /// + private bool header = false; + + /// + /// Internal value if we've written our first line before + /// + private bool firstRow = false; + + /// + /// Internal value to say how many fields should be written + /// + private int fields = -1; + + /// + /// Set if values should be wrapped in quotes + /// + public bool Quotes { get; set; } = true; + + /// + /// Set what string should be used as a separator + /// + public string Separator { get; set; } = ","; + + /// + /// Set if field count should be verified from the first row + /// + public bool VerifyFieldCount { get; set; } = true; + + /// + /// Constructor for writing to a file + /// + public SeparatedValueWriter(string filename) + { + sw = new StreamWriter(filename); + } + + /// + /// Consturctor for writing to a stream + /// + public SeparatedValueWriter(Stream stream, Encoding encoding) + { + sw = new StreamWriter(stream, encoding); + } + + /// + /// Write a header row + /// + public void WriteHeader(string[] headers) + { + // If we haven't written anything out, we can write headers + if (!header && !firstRow) + WriteValues(headers); + + header = true; + } + + /// + /// Write a value row + /// + public void WriteValues(object[] values) + { + // If the writer can't be used, we error + if (sw == null || !sw.BaseStream.CanWrite) + throw new ArgumentException(nameof(sw)); + + // If the separator character is invalid, we error + if (string.IsNullOrEmpty(Separator)) + throw new ArgumentException(nameof(Separator)); + + // If we have the first row, set the bool and the field count + if (!firstRow) + { + firstRow = true; + if (VerifyFieldCount && fields == -1) + fields = values.Length; + } + + // Get the number of fields to write out + int fieldCount = values.Length; + if (VerifyFieldCount) + fieldCount = Math.Min(fieldCount, fields); + + // Iterate over the fields, writing out each + bool firstField = true; + for (int i = 0; i < fieldCount; i++) + { + var value = values[i]; + + if (!firstField) + sw.Write(Separator); + + if (Quotes) + sw.Write("\""); + sw.Write(value.ToString()); + if (Quotes) + sw.Write("\""); + + firstField = false; + } + + // If we need to pad out the number of fields, add empties + if (VerifyFieldCount && values.Length < fields) + { + for (int i = 0; i < fields - values.Length; i++) + { + sw.Write(Separator); + + if (Quotes) + sw.Write("\"\""); + } + } + + // Add a newline + sw.WriteLine(); + + // Flush the buffer + sw.Flush(); + } + + /// + /// Dispose of the underlying writer + /// + public void Dispose() + { + sw.Dispose(); + } + } +}