Skip to content

Instantly share code, notes, and snippets.

@Restuta
Created September 22, 2010 22:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Restuta/592737 to your computer and use it in GitHub Desktop.
Save Restuta/592737 to your computer and use it in GitHub Desktop.
CsvFieldsSaver + Tests
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Restuta;
using System.Text;
namespace Restuta.FieldSavers
{
/// <summary>
/// Writes provided list of values to CSV file.
/// </summary>
public class CsvFieldsSaver : IFormFieldsSaver
{
private readonly TextWriter fileWriter;
private const string Comma = ",";
private static readonly string LineBreak = Environment.NewLine;
private const string DoubleQuote = @"""";
/// <summary>
/// Initializes a new instance of the <see cref="CsvFieldsSaver"/> class.
/// </summary>
/// <param name="fileWriter">The file writer.</param>
public CsvFieldsSaver(TextWriter fileWriter)
{
fileWriter.ThrowIfNull("fileWriter");
this.fileWriter = fileWriter;
}
/// <summary>
/// Saves form values in CSV format using provided <see cref="TextWriter"/>.
/// </summary>
/// <param name="values"></param>
/// <returns></returns>
public void Save(IEnumerable<FormItem> values)
{
values.ThrowIfNull("values");
this.Write(values.Select(x => x.DisplayName));
this.fileWriter.Write(LineBreak);
this.Write(values.Select(x => x.Value));
}
/// <summary>
/// Writes the specified items using <see cref="TextWriter"/>.
/// </summary>
/// <param name="items">The items.</param>
private void Write(IEnumerable<string> items)
{
List<string> enclosedItems = EncloseItemsAccordingToCsvStandard(items);
this.fileWriter.Write(string.Join(",", enclosedItems.ToArray()));
}
private static List<string> EncloseItemsAccordingToCsvStandard(IEnumerable<string> items)
{
List<string> itemsCopy = new List<string>(items.Count());
foreach (var item in items)
{
string quotedItem = null;
if (item == null)
{
itemsCopy.Add(string.Empty);
continue;
}
if (item.Contains(DoubleQuote))
{
quotedItem = QuoteEachDoubleQuote(item);
}
if (item.Contains(Comma) || item.Contains(LineBreak) || item.Contains(DoubleQuote)
|| HasLeadingOrTrailingSpaces(item))
{
string enclosedItem = string.Format("\"{0}\"", quotedItem ?? item);
itemsCopy.Add(enclosedItem);
}
else
{
itemsCopy.Add(item);
}
}
return itemsCopy;
}
private static string QuoteEachDoubleQuote(string item)
{
const string TwoDoubleQuotes = "\"\"";
return item.Replace(DoubleQuote, TwoDoubleQuotes);
}
private static bool HasLeadingOrTrailingSpaces(string item)
{
return item.Length != item.Trim().Length;
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using NUnit.Framework;
using Rhino.Mocks;
using System.Linq;
using Restuta.FieldSavers;
// ReSharper disable PublicMembersMustHaveComments
// ReSharper disable IdentifierWordIsNotInDictionary
namespace Restuta.Tests.FieldSavers
{
[TestFixture]
public class CsvFieldsSaverFixture
{
private TextWriter textWriter;
[SetUp]
public void SetUp()
{
this.textWriter = MockRepository.GenerateMock<TextWriter>();
}
[Test]
public void Ctor_ShouldNotThrow()
{
var csvWriter = new CsvFieldsSaver(this.textWriter);
}
[Test]
public void Ctor_NullPassed_ShouldThrow()
{
Assert.Throws<ArgumentNullException>(() => new CsvFieldsSaver(null));
}
[Test]
public void Save_NullPassed_ShouldThrow()
{
Assert.Throws<ArgumentNullException>(() => new CsvFieldsSaver(textWriter).Save(null));
}
[Test]
public void Save_SeveralItemsPassed_ShouldWriteToWriter()
{
//arrange
var fileWriter = new FileWriter(new StreamWriter(new MemoryStream()));
var csvWriter = new CsvFieldsSaver(fileWriter);
List<FormItem> items = this.GetFormItems("item1", "item2");
//act
csvWriter.Save(items);
//assert
MemoryStream memoryStream = (MemoryStream)fileWriter.StreamWriter.BaseStream;
memoryStream.Position = 0;
string result = this.GetResult(memoryStream);
Assert.That(result, Is.EqualTo(@"," + Environment.NewLine + @"item1,item2"));
}
[Test]
public void Save_ItemWithComma_ShouldBeEnclosedWithDoubleQuotedCharacter()
{
//arrange
var memoryStream = new MemoryStream();
var fileWriter = new FileWriter(new StreamWriter(memoryStream));
var csvWriter = new CsvFieldsSaver(fileWriter);
List<FormItem> items = this.GetFormItems("ite,m1", "item2");
//act
csvWriter.Save(items);
//assert
string result = this.GetResult(memoryStream);
Assert.That(result, Is.EqualTo(@"," + Environment.NewLine + @"""ite,m1"",item2"));
}
[Test]
public void Save_EmptyItem_ShouldWriteEmpty()
{
//arrange
var memoryStream = new MemoryStream();
var fileWriter = new FileWriter(new StreamWriter(memoryStream));
var csvWriter = new CsvFieldsSaver(fileWriter);
List<FormItem> items = this.GetFormItems("item1", string.Empty);
//act
csvWriter.Save(items);
//assert
string result = this.GetResult(memoryStream);
Assert.That(result, Is.EqualTo(",\r\nitem1,"));
}
[Test]
public void Save_ItemsWithDoubleQuotes_ShouldBeEnclosedToDoubleQuotesAndQuotedEachDoubleQuote()
{
//arrange
var memoryStream = new MemoryStream();
var fileWriter = new FileWriter(new StreamWriter(memoryStream));
var csvWriter = new CsvFieldsSaver(fileWriter);
List<FormItem> items = this.GetFormItems(@"it""e""m1", "item2");
//act
csvWriter.Save(items);
//assert
string result = this.GetResult(memoryStream);
Assert.That(result, Is.EqualTo(@"," + Environment.NewLine + @"""it""""e""""m1"",item2"));
}
[Test]
public void Save_ItemsWithLeadingOrTrailingSpaces_MustBeEnclosedWithDoubleQuotes()
{
//arrange
var memoryStream = new MemoryStream();
var fileWriter = new FileWriter(new StreamWriter(memoryStream));
var csvWriter = new CsvFieldsSaver(fileWriter);
List<FormItem> items = this.GetFormItems(@" item1 ", "item2");
//act
csvWriter.Save(items);
//assert
string result = this.GetResult(memoryStream);
Assert.That(result, Is.EqualTo(@"," + Environment.NewLine + @""" item1 "",item2"));
}
[Test]
public void Save_ItemsWithEmbeddedLineBrakes_MustBeEnclosedWithDoubleQuotes()
{
//arrange
var memoryStream = new MemoryStream();
var fileWriter = new FileWriter(new StreamWriter(memoryStream));
var csvWriter = new CsvFieldsSaver(fileWriter);
List<FormItem> items = this.GetFormItems(@"ite" + Environment.NewLine + @"m1", "item2");
//act
csvWriter.Save(items);
//assert
string result = this.GetResult(memoryStream);
Assert.That(result, Is.EqualTo(@"," + Environment.NewLine + @"""ite" + Environment.NewLine + @"m1"",item2"));
}
[Test]
public void Save_ShouldWriteItemsWithHeaders()
{
//arrange
var memoryStream = new MemoryStream();
var fileWriter = new FileWriter(new StreamWriter(memoryStream));
var csvWriter = new CsvFieldsSaver(fileWriter);
List<FormItem> items = new List<FormItem>
{
new FormItem { Value = "item1", DisplayName = "HeaderItem1"},
new FormItem { Value = "item2", DisplayName = "HeaderItem2"}
};
//act
csvWriter.Save(items);
//assert
string result = this.GetResult(memoryStream);
Assert.That(result, Is.EqualTo(@"HeaderItem1,HeaderItem2" + Environment.NewLine + @"item1,item2"));
}
[Test]
public void Save_ItemsHasNullDisplayNames_ShouldWriteAsEmptyStrings()
{
//arrange
var memoryStream = new MemoryStream();
var fileWriter = new FileWriter(new StreamWriter(memoryStream));
var csvWriter = new CsvFieldsSaver(fileWriter);
List<FormItem> items = new List<FormItem>
{
new FormItem { Value = "item1", DisplayName = null},
new FormItem { Value = "item2", DisplayName = null}
};
//act
csvWriter.Save(items);
//assert
string result = this.GetResult(memoryStream);
Assert.That(result, Is.EqualTo(@"," + Environment.NewLine + @"item1,item2"));
}
[Test]
public void Save_ItemsWithCommasInDisplayName_ShouldBeQuoted()
{
//arrange
var memoryStream = new MemoryStream();
var fileWriter = new FileWriter(new StreamWriter(memoryStream));
var csvWriter = new CsvFieldsSaver(fileWriter);
List<FormItem> items = new List<FormItem>
{
new FormItem { Value = "item1", DisplayName = "Header,Item1"},
new FormItem { Value = "item2", DisplayName = "HeaderItem2"}
};
//act
csvWriter.Save(items);
//assert
string result = this.GetResult(memoryStream);
Assert.That(result, Is.EqualTo(@"""Header,Item1"",HeaderItem2"+ Environment.NewLine +"item1,item2"));
}
#region private members
private string GetResult(MemoryStream memoryStream)
{
string result = null;
memoryStream.Position = 0;
using (var reader = new StreamReader(memoryStream))
{
result = reader.ReadToEnd();
}
return result;
}
private List<FormItem> GetFormItems(params string[] items)
{
var formItems = new List<FormItem>();
formItems.AddRange(items.Select(x => new FormItem {Value = x}));
return formItems;
}
#endregion
}
}
// ReSharper restore PublicMembersMustHaveComments
// ReSharper restore IdentifierWordIsNotInDictionary
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment