59

我有以下方法:

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 都会以零长度返回,并且没有任何内容传递给它。我以前用过这个,但由于某种原因它不起作用——我有点困惑。谁能指出我在这里做错了什么?

干杯

4

5 回答 5

70

你已经有了一个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,你需要小心。这将在每次写入后刷新。如果您的流是网络流并且通过网络传输,它会非常慢。

于 2014-04-10T19:54:42.257 回答
42

csvWriter.Flush();在您返回以刷新写入器/流之前放置。

编辑:根据杰克的回应。它应该是被刷新的流,而不是 csvWriter。streamWriter.Flush();. 保留原始解决方案,但添加此更正。

编辑 2:我的首选答案是:https ://stackoverflow.com/a/22997765/1795053让 using 语句为您完成繁重的工作

于 2012-11-30T16:30:14.717 回答
27

将所有这些放在一起(以及更正的评论),包括重置内存流位置,我的最终解决方案是;

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

以防万一帮助别人!

于 2016-10-26T06:41:14.830 回答
9

csvWriter中没有flush,flush在streamWriter中。调用时

csvWriter.Dispose();

它将刷新流。另一种方法是设置

streamWriter.AutoFlush = true;

每次都会自动刷新流。

于 2012-12-19T08:10:57.040 回答
7

这是工作示例:

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

基于这个答案。

于 2017-11-01T22:01:32.727 回答