CsvHelper не пишет ничего в поток памяти

У меня есть следующий метод:

public byte[] WriteCsvWithHeaderToMemory<T>(IEnumerable<T> records) where T : class
{
    using (var memoryStream = new MemoryStream())
    using (var streamWriter = new StreamWriter(memoryStream))
    using (var csvWriter = new CsvWriter(streamWriter))
    {
        csvWriter.WriteRecords<T>(records);

        return memoryStream.ToArray();
    }
}

Который вызывается со списком объектов - в конечном итоге из базы данных, но поскольку что-то не работает, я просто заполняю статическую коллекцию. Передаваемые объекты:

using CsvHelper.Configuration;

namespace Application.Models.ViewModels
{
    public class Model
    {
        [CsvField(Name = "Field 1", Ignore = false)]
        public string Field1 { get; set; }

        [CsvField(Name = "Statistic 1", Ignore = false)]
        public int Stat1{ get; set; }

        [CsvField(Name = "Statistic 2", Ignore = false)]
        public int Stat2{ get; set; }

        [CsvField(Name = "Statistic 3", Ignore = false)]
        public int Stat3{ get; set; }

        [CsvField(Name = "Statistic 4", Ignore = false)]
        public int Stat4{ get; set; }
    }
}

То, что я пытаюсь сделать, это написать коллекцию в csv для загрузки в приложении MVC. Каждый раз, когда я пытаюсь написать метод, MemoryStream возвращается с нулевой длиной и ничего не передается ему. Я использовал это раньше, но по какой-то причине он просто не работает - я несколько смущен. Может ли кто-нибудь указать мне, что я сделал здесь неправильно?

ура

Ответ 1

Поместите csvWriter.Flush(); перед возвратом, чтобы очистить устройство записи/поток.

ОБНОВЛЕНИЕ: в ответ на Джек. Должен быть сброшен поток, а не csvWriter. streamWriter.Flush();. Оставив оригинальное решение, но добавив это исправление.

ОБНОВЛЕНИЕ 2: Мой предпочтительный ответ: fooobar.com/questions/5890096/... Пусть использование операторов сделает тяжелую работу для вас

Ответ 2

У вас уже есть, using блок, который является большим. Это поможет вашему писателю. Вы можете просто немного изменить свой код, чтобы он работал.

using (var memoryStream = new MemoryStream())
{
    using (var streamWriter = new StreamWriter(memoryStream))
    using (var csvWriter = new CsvWriter(streamWriter))
    {
        csvWriter.WriteRecords<T>(records);
    } // StreamWriter gets flushed here.

    return memoryStream.ToArray();
}

Если вы включите AutoFlush, вам нужно быть осторожным. Это будет сбрасываться после каждой записи. Если ваш поток является сетевым потоком и по кабелю, он будет очень медленным.

Ответ 3

Объединив все это (и комментарии для исправлений), включая сброс позиции потока памяти, окончательное решение для меня было;

        using (MemoryStream ms = new MemoryStream())
        {
            using (TextWriter tw = new StreamWriter(ms))
            using (CsvWriter csv = new CsvWriter(tw))
            {
                csv.WriteRecords(errors); // Converts error records to CSV

                tw.Flush(); // flush the buffered text to stream
                ms.Seek(0, SeekOrigin.Begin); // reset stream position

                Attachment a = new Attachment(ms, "errors.csv"); // Create attachment from the stream
                // I sent an email here with the csv attached.
            }
        }

В случае, если кто-то помог!

Ответ 4

В csvWriter нет флеша, флеш находится в streamWriter. Когда вызывается

csvWriter.Dispose();

он будет смывать поток. Другой подход - установить

streamWriter.AutoFlush = true;

который будет автоматически очищать поток каждый раз.

Ответ 5

Вот рабочий пример:

void Main()
{
    var records = new List<dynamic>{
       new { Id = 1, Name = "one" },
       new { Id = 2, Name = "two" },
    };

    Console.WriteLine(records.ToCsv());
}

public static class Extensions {
    public static string ToCsv<T>(this IEnumerable<T> collection)
    {
        using (var memoryStream = new MemoryStream())
        {
            using (var streamWriter = new StreamWriter(memoryStream))
            using (var csvWriter = new CsvWriter(streamWriter))
            {
                csvWriter.WriteRecords(collection);
            } // StreamWriter gets flushed here.

            return Encoding.ASCII.GetString(memoryStream.ToArray());
        }
    }
}

На основании этого ответа.