using System;
using System.IO;
using System.Text;
namespace SabreTools.Library.IO
{
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 character should be used as a separator
///
public char 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, bool newline = true)
{
// 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 (Separator == default(char))
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() ?? string.Empty);
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, if needed
if (newline)
sw.WriteLine();
}
///
/// Write a generic string
///
public void WriteString(string value)
{
if (string.IsNullOrEmpty(value))
return;
sw.Write(value);
}
///
/// Write a newline
///
public void WriteLine()
{
sw.WriteLine();
}
///
/// Flush the underlying writer
///
public void Flush()
{
sw.Flush();
}
///
/// Dispose of the underlying writer
///
public void Dispose()
{
sw.Dispose();
}
}
}