【问题标题】:CsvHelper not writing anything to memory streamCsvHelper 没有向内存流写入任何内容
【发布时间】:2012-11-18 17:25:43
【问题描述】:

我有以下方法:

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

干杯

【问题讨论】:

  • 你试过刷新你的流吗?在返回之前输入csvWriter.Flush();
  • 谢谢。我知道这会很愚蠢,但我已经失去了半个上午的时间,盯着它想不出什么问题......
  • 这行得通吗?伟大的。您希望我将其作为未来搜索者的答案提交还是您自己提交解决方案?
  • 如果您能提交一份,我会检查答案,以便您获得信用。
  • 现在不支持CsvField属性,可以使用CsvClassMap注册为:csv.Configuration.RegisterClassMap(new MyClassMap);

标签: c# csvhelper


【解决方案1】:

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

【讨论】:

  • 我认为这是不正确的。如果这样做,StreamWriter 将被刷新,但它也会处理底层流。
  • 是的,return 应该在 using 块内。
  • 似乎 CsvWriter 在 3.0.0.0 版本中有两个错误。它不会在 Dispose 时刷新。这是一回事,第二个是第一条记录没有用新行与标题分隔。所以刷新 csvWriter 是一个必要的解决方法。
  • 请在 GitHub 上提交错误,我会尽快修复
  • @RadekStrugalski 修复了第一个问题。第二个你现在需要手动调用NextRecord()。这是为了给用户更多的控制权。您可以通过这种方式编写标题并进行更多手动编写。
【解决方案2】:

在您返回刷新写入器/流之前输入csvWriter.Flush();

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

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

【讨论】:

  • 这是一个错误的答案。 CsvWriter 上没有 Flush 方法。
  • 我的首选答案是:stackoverflow.com/a/22997765/1795053using 语句为您完成繁重的工作。
  • streamwriter.Flush();为我工作。谢谢你的帮助。还要感谢@JackHughes
  • 在 CsvHelper >= 17 上有一个 Flush,这对我有用。
【解决方案3】:

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

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

以防万一帮助别人!

【讨论】:

  • ms.Seek(0, SeekOrigin.Begin); 对我来说是缺失的部分。刷新,使用语句,在我重置流之前没有任何区别。
  • 答案不起作用,可能已过时。 CsvWriter(tw) 不再只接受一个参数,即使添加它仍然会抛出一个错误,抱怨关闭的内存流。
【解决方案4】:

csvWriter中没有flush,flush在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());
            }
        }
    }
    

    基于this 的回答。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-30
      • 2018-02-19
      • 1970-01-01
      • 2021-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多