Подтвердить что ты не робот

Как преобразовать список объектов в csv?

Если у меня есть список объектов под названием "Автомобиль":

public class Car
{
     public string Name;
     public int Year;
     public string Model;
}

Как преобразовать список объектов, например. Список < & автомобилей GT; к csv?

4b9b3361

Ответ 1

  • FileHelpers Библиотека
  • Текстовый поставщик OleDb
  • Руководство по конкатенации строк в соответствии с RFC-4180
  • Сторонняя библиотека, например Aspose.Cells, может сделать это без каких-либо трений от вас. И это очень быстро.

Ответ 2

Посмотрите на библиотеку 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.

Ответ 3

добавьте в 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);
}

Ответ 4

Я искал решение для этого, но ни один из ответов, которые я нашел, не удовлетворил мой привод для простоты. Я понял, что уже получил ответ с моим кодом 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);

Вероятно, есть лучший способ написать эти два метода выше, но это отлично работает для моей ситуации. Надеюсь, это поможет кому-то.

Ответ 5

Вы можете просто переопределить метод 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());
            }
        }

Ответ 6

Объединяя значения, разделенные запятыми, мне всегда нравится указывать на сильно недооцененный статический метод string.Join(string separator, string[] elements), но если есть вспомогательные библиотеки, это, вероятно, лучший материал.

Ответ 7

Я бы выполнил некоторые дополнительные методы сериализации в соответствии с этой статьей. Если вы хотите получить фантазию, вы можете создать настройку в своих проектах. Этот параметр определяет, использует ли ваш класс 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
   {
   }
}

Это должно начаться., Я не компилировал и не тестировал это., но вы получите общую идею.