Вопрос по c#, .net – Объект объекта в сериализацию / преобразование CSV

15

Как я могу записать все значения (свойства) в форматированную строку CSV в C #? например.:

class Person(string firstName, string lastName, int_age);
Person person = new Person("Kevin","Kline",33);

теперь я хочу строку"Kevin;Kline;33"

Другими словами, я хочу сериализовать объект в CSV

значения чего? Mare Infinitus
Ваш вопрос нуждается в большем количестве справочной информации и примеров данных / кода, чтобы не быть кандидатом на закрытие. KP.
@nonnb: вы можете опубликовать это как ответ, это полезно. Groo
Кроме того, это, возможно, незначительный зазор, но в формате значений, разделенных запятыми, для разделения значений используются запятые. Вы, кажется, используете точки с запятой. Thom Smith
Можете ли вы показать нам, что вы уже пробовали? LolCat

Ваш Ответ

6   ответов
2

FileHelpers это хорошо, я сам не использовал это в гневе, хотя

Это хорошо. Жаль, что он не работает для .Net Core, хотя: / CSVHelper работает !!
0

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 - подходящая экранирующая функция.

13

Джош Клоуз отлично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
Самое приятное, что он доступен для .Net Core.
Можно ли использовать CSVHelper без сохранения файла file.csv? Я не хочу записывать файл на жестком диске, я намерен отправить файл в ответ веб-пользователю.
2

...
        PropertyInfo[] properties = obj.GetType().GetProperties();
        string CSVRow = "";
        foreach (PropertyInfo pi in properties)
        {
            CSVRow = CSVRow + pi.GetValue(obj, null) + ";";
        }
        CSVRow.Remove(CSVRow.Length - 1, 1);
...
... но также необходимо реализовать правила цитирования / экранирования.
9

вы можете получить информацию о свойствах объекта

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());

Также полезно заключать строки в двойные кавычки и избегать двойных кавычек, которые они содержат, удваивая их.

0

Одна возможная реализация для вас, которая читает сложные объекты (глубокая сериализация объектов), например, массив объектов со свойствами, которые являются массивом объектов, и сохраняет строку, отформатированную как 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();
}

Похожие вопросы