Если у меня есть список объектов под названием "Автомобиль":
public class Car
{
public string Name;
public int Year;
public string Model;
}
Как преобразовать список объектов, например. Список < & автомобилей GT; к csv?
Если у меня есть список объектов под названием "Автомобиль":
public class Car
{
public string Name;
public int Year;
public string Model;
}
Как преобразовать список объектов, например. Список < & автомобилей GT; к csv?
Посмотрите на библиотеку FileHelpers.
С сайта:
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.
Это позволит убедиться, что все виды ошибок в завершении линии, экранирование и т.д. обрабатываются правильно, согласно RFC-4180.
добавьте в 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");
}
Теперь вы можете сериализовать весь список:
foreach (Car car in list)
{
car.SerializeAsCsv(stream);
}
Я искал решение для этого, но ни один из ответов, которые я нашел, не удовлетворил мой привод для простоты. Я понял, что уже получил ответ с моим кодом CRUD. Я перепрофилировал его и придумал следующий код:
using System.Reflection;
/// <summary>
/// Using a bit of reflection to build up the strings.
/// </summary>
public static string ToCsvHeader(this object obj)
{
Type type = obj.GetType();
var properties = type.GetProperties(BindingFlags.DeclaredOnly |
BindingFlags.Public |
BindingFlags.Instance);
string result = string.Empty;
Array.ForEach(properties, prop =>
{
result += prop.Name + ",";
});
return (!string.IsNullOrEmpty(result) ? result.Substring(0, result.Length - 1) : result);
}
public static string ToCsvRow(this object obj)
{
Type type = obj.GetType();
var properties = type.GetProperties(BindingFlags.DeclaredOnly |
BindingFlags.Public |
BindingFlags.Instance);
string result = string.Empty;
Array.ForEach(properties, prop =>
{
var value = prop.GetValue(obj, null);
var propertyType = prop.PropertyType.FullName;
if (propertyType == "System.String")
{
// wrap value incase of commas
value = "\"" + value + "\"";
}
result += value + ",";
});
return (!string.IsNullOrEmpty(result) ? result.Substring(0, result.Length - 1) : result);
}
Это добавит метод расширения для каждого объекта. Использование:
var burgers = new List<Cheeseburger>();
var output = burgers.ToCsvHeader();
output += Environment.NewLine;
burgers.ForEach(burger =>
{
output += burger.ToCsvRow();
output += Environment.NewLine;
});
var path = "[where ever you want]";
System.IO.File.WriteAllText(path, output);
Вероятно, есть лучший способ написать эти два метода выше, но это отлично работает для моей ситуации. Надеюсь, это поможет кому-то.
Вы можете просто переопределить метод ToString или создать метод ToCSVRow() как таковой
public String ToCSVRow()
{
return Name + "," + Year.ToString() + "," + Model;
}
И тогда просто сделайте что-нибудь подобное, когда это необходимо.
using (StreamWriter file = new StreamWriter(@"C:\Wherever\yourfilename.txt"))
{
foreach (var item in yourlist)
{
file.WriteLine(item.ToCSVRow());
}
}
Объединяя значения, разделенные запятыми, мне всегда нравится указывать на сильно недооцененный статический метод string.Join(string separator, string[] elements)
, но если есть вспомогательные библиотеки, это, вероятно, лучший материал.
Я бы выполнил некоторые дополнительные методы сериализации в соответствии с этой статьей. Если вы хотите получить фантазию, вы можете создать настройку в своих проектах. Этот параметр определяет, использует ли ваш класс csv или сериализацию по умолчанию. Затем вы получите доступ к ним с помощью методов, представленных здесь. Рассмотрите возможность использования статического конструктора для чтения настроек appsettings и создания логического значения, доступного для вашего кода сериализации. Код Влада выглядит великолепно, просто подключите его к вашему коду. Также вы можете подумать о других, возможно, более желательных способах изменения поведения в процессе сериализации.
Или создайте интерфейс под названием "SerializeAsCSV" и используйте его вроде как:
//Частичное содержимое 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
}
}
//содержимое ISerializeAsCSV.cs
using System.Runtime.Serialization;
namespace GrooveySoft.Shared.Interfaces
{
/// <summary>
/// indicates that implementor will serialize to csv format
/// </summary>
public interface ISerializeAsCSV : ISerializable
{
}
}
Это должно начаться., Я не компилировал и не тестировал это., но вы получите общую идею.
Другим вариантом является Linq to CSV - пакет, доступный от NuGet. См. Объединить содержимое двух файлов, используя LINQ to CSV, например, использование.