Объектная сущность для сериализации/преобразования CSV
Как я могу написать все значения (свойства) в csv форматированную строку в С#?
например:.
class Person(string firstName, string lastName, int_age);
Person person = new Person("Kevin","Kline",33);
теперь я хочу строку "Кевин, Клайн, 33"
Другими словами, я хочу сериализовать объект в CSV
Ответы
Ответ 1
Посмотрите Josh Close отлично CSVHelper библиотека
var person = new Person("Kevin","Kline",33);
using (var csv = new CsvWriter(new StreamWriter("file.csv")))
{
csv.Configuration.HasHeaderRecord = false;
csv.Configuration.Delimiter = ';';
csv.WriteRecord(person);
}
Вывод:
Kevin;Kline;33
Ответ 2
Используя отражение, вы можете получить информацию об объекте из объекта
foreach (PropertyInfo prp in obj.GetType().GetProperties()) {
if (prp.CanRead) {
object value = prp.GetValue(obj, null);
string s = value == null ? "" : value.ToString();
string name = prp.Name;
...
}
}
Метод GetProperties
имеет перегрузку, принимающую BindingFlags
, через которую вы можете определить, какой тип свойства вам нужен, например private/public instance/static.
Вы можете комбинировать их так:
var properties = type.GetProperties(BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance);
Применительно к вашей проблеме вы можете написать
List<Person> people = ...;
Type type = typeof(Person);
PropertyInfo[] properties = type.GetProperties();
var sb = new StringBuilder();
// First line contains field names
foreach (PropertyInfo prp in properties) {
if (prp.CanRead) {
sb.Append(prp.Name).Append(';');
}
}
sb.Length--; // Remove last ";"
sb.AppendLine();
foreach (Person person in people) {
foreach (PropertyInfo prp in properties) {
if (prp.CanRead) {
sb.Append(prp.GetValue(person, null)).Append(';');
}
}
sb.Length--; // Remove last ";"
sb.AppendLine();
}
File.AppendAllText("C:\Data\Persons.csv", sb.ToString());
Также неплохо вложить строки в двойные кавычки и избежать котировок двойников, которые они содержат, удваивая их.
Ответ 3
вы можете использовать что-то вроде этого:
...
PropertyInfo[] properties = obj.GetType().GetProperties();
string CSVRow = "";
foreach (PropertyInfo pi in properties)
{
CSVRow = CSVRow + pi.GetValue(obj, null) + ";";
}
CSVRow.Remove(CSVRow.Length - 1, 1);
...
Ответ 4
Я верю, что FileHelpers хорош для этого, я сам не использовал его в гневе, хотя
Ответ 5
Что-то вроде этого:
public string ToCsv()
{
return string.Join(";", new string[]{
_firstName,
_lastName,
_age.ToString()
}.Select(str=>Escape(str)));
}
Или, используя отражение,
public static string ToCsv(this object obj)
{
return string.Join(";",
this.GetType().GetProperties().Select(pi=>
Escape(pi.GetValue(this, null).ToString())
));
}
Где Escape - соответствующая функция экранирования.
Ответ 6
Одна возможная реализация для вас, которая читает сложные объекты (сериализация глубоких объектов), подобно массиву объектов со свойствами, которые представляют собой массив объектов, и сохраняет строку, отформатированную как CSV файл:
private string ToCsv(string separator, IEnumerable<object> objectList)
{
StringBuilder csvData = new StringBuilder();
foreach (var obj in objectList)
{
csvData.AppendLine(ToCsvFields(separator, obj));
}
return csvData.ToString();
}
private string ToCsvFields(string separator, object obj)
{
var fields = obj.GetType().GetProperties();
StringBuilder line = new StringBuilder();
if (obj is string)
{
line.Append(obj as string);
return line.ToString();
}
foreach (var field in fields)
{
var value = field.GetValue(obj);
var fieldType = field.GetValue(obj).GetType();
if (line.Length > 0)
{
line.Append(separator);
}
if (value == null)
{
line.Append("NULL");
}
if (value is string)
{
line.Append(value as string);
}
if (typeof(IEnumerable).IsAssignableFrom(fieldType))
{
var objectList = value as IEnumerable;
StringBuilder row = new StringBuilder();
foreach (var item in objectList)
{
if (row.Length > 0)
{
row.Append(separator);
}
row.Append(ToCsvFields(separator, item));
}
line.Append(row.ToString());
}
else
{
line.Append(value.ToString());
}
}
return line.ToString();
}