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

Ура

5 ответов


поставить csvWriter.Flush(); прежде чем вы вернетесь, чтобы очистить writer/stream.

EDIT: за ответ Джека. Это должен быть поток, который сбрасывается, а не csvWriter. streamWriter.Flush();. Оставляя оригинальное решение, но добавляя эту поправку.


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


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

csvWriter.Dispose();

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

модулю записи StreamWriter.AutoFlush = true;

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


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

        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.
            }
        }

в случае, если это помогает кто-то другой!


вот пример:

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

на основе этой ответ.