web-dev-qa-db-ja.com

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

私がやろうとしていることは、MVCアプリケーションでダウンロードするために、CSVにコレクションを書き込むことです。しかし、メソッドに書き込もうとするたびに、MemoryStreamは長さがゼロで戻り、何も渡されません。私は以前これを使用したことがありますが、何らかの理由でそれが機能しないだけです-少し混乱しています。私がここで間違ったことを誰かが私に指摘することはできますか?

乾杯

40
Ian Cotterill

戻る前にcsvWriter.Flush();を書き込んで、ライター/ストリームをフラッシュします。

編集:ジャックごとの応答。フラッシュされるのはcsvWriterではなくストリームです。 streamWriter.Flush();。元のソリューションを残して、この修正を追加します。

編集2:私の好ましい答えは次のとおりです: https://stackoverflow.com/a/22997765/179505 usingステートメントにあなたのために重い仕事をさせましょう

27
Eli Gassert

あなたはすでに素晴らしい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をオンにする場合は、注意が必要です。これはすべての書き込み後にフラッシュされます。ストリームがネットワークストリームであり、ネットワーク経由の場合は、非常に遅くなります。

47
Josh Close

メモリストリームの位置のリセットを含め、これらすべて(および修正に関するコメント)をまとめると、私にとっての最終的な解決策は次のとおりでした。

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

が誰かを助ける場合に!

19
Josh

CsvWriterにはフラッシュはありません。フラッシュはstreamWriterにあります。呼ばれたとき

csvWriter.Dispose();

ストリームをフラッシュします。別のアプローチは設定することです

streamWriter.AutoFlush = true;

毎回自動的にストリームをフラッシュします。

9
TuomasK

これが実際の例です:

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 の回答に基づいています。

6
Amit