if i have a list of objects called "Car"
public class Car
{
public string Name;
public int Year;
public string Model;
}
and i have a list of List and i want to generate a csv file dynamically from this list
if i have a list of objects called "Car"
public class Car
{
public string Name;
public int Year;
public string Model;
}
and i have a list of List and i want to generate a csv file dynamically from this list
Look at the FileHelpers library.
From the site:
The FileHelpers are a free and easy to use .NET library to import/export data from fixed length or delimited records in files, strings or streams.
This will make sure that all kinds of gotchas in line termination, escaping and such are handled correctly, as per RFC-4180.
Use StringBuilder..
var sb = new StringBuilder();
foreach(var o in objects)
sb.Append(string.format("Name:{0} Year:{1} Model{2},",
o.Name, o.Year, o.Model));
var csv = sb.ToString(0, sb.Length - 1);
If you overrde ToString()
appropriately in the Car class all you need is:
var sb = new StringBuilder();
foreach(var o in objects)
sb.Append(string.format("{0},", o));
var csv = sb.ToString(0, sb.Length - 1);
Putting together comma-separated values I always like to point at the much underrated string.Join(string separator, string[] elements)
static method, but if there are helper libraries out there, that's probably better stuff.
add the following method to Car:
String Escape(String s)
{
StringBuilder sb = new StringBuilder();
bool needQuotes = false;
foreach (char c in s.ToArray())
{
switch (c)
{
case '"': sb.Append("\\\""); needQuotes = true; break;
case ' ': sb.Append(" "); needQuotes = true; break;
case ',': sb.Append(","); needQuotes = true; break;
case '\t': sb.Append("\\t"); needQuotes = true; break;
case '\n': sb.Append("\\n"); needQuotes = true; break;
default: sb.Append(c); break;
}
}
if (needQuotes)
return "\"" + sb.ToString() + "\"";
else
return sb.ToString();
}
public void SerializeAsCsv(Stream stream)
{
stream.Write(Escape(Name));
stream.Write(",");
stream.Write(Year.ToString());
stream.Write(",");
stream.Write(Escape(Model));
stream.Write("\n");
}
Now you can serialize the whole list:
foreach (Car car in list)
{
car.SerializeAsCsv(stream);
}
I'd implement some addtional serialzation behaviors as per this article. If you want to get fancy, you can create a setting in your projects properties. This setting would determine if your class used csv or default serialialization. You'd then access it through the techniques shown here. Consider using a static constructor to read appsettings and make a boolean value accessable to your serialization code. Vlads' code looks great, just plug it in to your code. Also you can consider other, maybe more desirable ways to change your serialzation behavior.
Or Create an interface called 'SerializeAsCSV' and use it kind of like this:
// Partial Contents of MyCoolClass.csv:
public class MyCoolClass : ISerializeAsCSV, IDisposable
{
protected static bool serializesToCSV = false;
static MyCoolClass()
{
serializesToCSV =
(typeof(MyCoolClass).GetInterface("GrooveySoft.Shared.Interfaces.ISerializeAsCSV") == null)
? false
: true;
}
public MyCoolClass(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
{
// your stuff here
}
public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
{
// your stuff here
}
}
// contents of ISerializeAsCSV.cs
using System.Runtime.Serialization;
namespace GrooveySoft.Shared.Interfaces
{
/// <summary>
/// indicates that implementor will serialize to csv format
/// </summary>
public interface ISerializeAsCSV : ISerializable
{
}
}
This should get your started . . . I haven't compiled and tested this . . but you get the general idea.