C# で Listデータ を CSVファイル へ 書き込む 方法

0 件のコメント

Listデータ を CSVファイル へ書き込むサンプルコードを作成しました。 読み込みがあるから書き込みもと思って作りましたが、単純に実装しています。

CSVフォーマットの仕様に関してはざっくりと CSVフォーマット の 仕様 に記載しました。

サンプルコード

受け取ったListデータをカンマ区切り(CSV)で出力します。

以下にあるコードをダブルクリックして選択、コピペすれば使える ハズ です。

CsvWriter.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
 
/// <summary>
/// CSV形式のストリームを書き込む CsvWriter を実装します。
/// </summary>
public class CsvWriter : IDisposable
{
    /// <summary>
    /// CSVファイルに書き込むストリーム
    /// </summary>
    private StreamWriter stream = null;
 
    /// <summary>
    /// ファイル名を指定して、 <see cref="CsvWriter">CsvWriter</see> クラスの新しいインスタンスを初期化します。
    /// </summary>
    /// <param name="path">書き込む完全なファイルパス。</param>
    public CsvWriter(string path) :
        this(path, Encoding.Default)
    {
    }
 
    /// <summary>
    /// ファイル名、文字エンコーディングを指定して、 <see cref="CsvWriter">CsvWriter</see> クラスの新しいインスタンスを初期化します。
    /// </summary>
    /// <param name="path">書き込む完全なファイルパス。</param>
    /// <param name="encoding">使用する文字エンコーディング。</param>
    public CsvWriter(string path, Encoding encoding)
    {
        var stream = new FileStream(path, FileMode.Create, FileAccess.ReadWrite);
        this.stream = new StreamWriter(stream, encoding);
    }
 
    /// <summary>
    /// 使用する文字エンコーディングを取得します。
    /// </summary>
    public Encoding Encoding
    {
        get
        {
            return this.stream.Encoding;
        }
    }
 
    /// <summary>
    /// 現在のストリームで利用される改行文字列を取得または設定します。
    /// </summary>
    public string NewLine
    {
        get
        {
            return this.stream.NewLine;
        }
 
        set
        {
            this.stream.NewLine = value;
        }
    }
 
    /// <summary>
    /// 現在のストリームオブジェクトと基になるストリームをとじます。
    /// </summary>
    public void Close()
    {
        if (this.stream == null)
        {
            return;
        }
 
        this.stream.Close();
    }
 
    /// <summary>
    /// CsvWriter で利用されているすべてのリソースを解放します。
    /// </summary>
    public void Dispose()
    {
        if (this.stream == null)
        {
            return;
        }
 
        this.stream.Close();
        this.stream.Dispose();
        this.stream = null;
    }
 
    /// <summary>
    /// 現在のライターで使用したすべてのバッファーをクリアし、バッファー内のすべてのデータをストリームに書き込みます。
    /// </summary>
    public void Flush()
    {
        this.stream.Flush();
    }
 
    /// <summary>
    /// 現在のライターで使用したすべてのバッファーを非同期的にクリアし、ストリームへ書き込みます。
    /// </summary>
    /// <returns>非同期のフラッシュ操作を表すタスク。</returns>
    public Task FlushAsync()
    {
        return this.stream.FlushAsync();
    }
 
    /// <summary>
    /// ストリームに文字を書き込みます。
    /// </summary>
    /// <typeparam name="T">リストの型。</typeparam>
    /// <param name="data">CSVデータ。</param>
    public void Write<T>(List<List<T>> data)
    {
        foreach (var row in data)
        {
            this.WriteRow<T>(row);
        }
    }
 
    /// <summary>
    /// ストリームに文字を非同期的に書き込みます。
    /// </summary>
    /// <typeparam name="T">リストの型。</typeparam>
    /// <param name="data">CSVデータ。</param>
    /// <returns>非同期の書き込み操作を表すタスク。</returns>
    public Task WriteAsync<T>(List<List<T>> data)
    {
        return Task.Factory.StartNew(() =>
        {
            this.Write<T>(data);
        });
    }
 
    /// <summary>
    /// ストリームに1レコード分の文字列を書き込みます。
    /// </summary>
    /// <typeparam name="T">リストの型。</typeparam>
    /// <param name="row">CSVの1レコード。</param>
    public void WriteRow<T>(List<T> row)
    {
        var sb = new StringBuilder();
 
        foreach(var cell in row)
        {
            var value = cell.ToString();
 
            if (value.Contains(this.NewLine) ||
                value.Contains(",") ||
                value.Contains("\""))
            {
                value = value.Replace("\"", "\"\"");
                sb.Append("\"");
                sb.Append(value);
                sb.Append("\"");
            }
            else
            {
                sb.Append(value);
            }
 
            sb.Append(",");
        }
 
        sb.Remove(sb.Length - 1, 1);
         
        this.stream.WriteLine(sb.ToString());
    }
 
    /// <summary>
    /// ストリームに1レコード分の文字列を非同期的に書き込みます。
    /// </summary>
    /// <typeparam name="T">リストの型。</typeparam>
    /// <param name="row">CSVの1レコード。</param>
    /// <returns>非同期の書き込み操作を表すタスク。</returns>
    public Task WriteRowAsync<T>(List<T> row)
    {
        return Task.Factory.StartNew(() =>
        {
            this.WriteRow<T>(row);
        });
    }
}

使用例

上記サンプルコードの利用例を以下に載せます。 サンプルコードには非同期メソッドも実装しましたが、ここでは同期メソッドの使用例だけあげます。

すべてのデータを書き込む使用例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using System;
using System.Collections.Generic;
 
class Program
{
    static void Main(string[] args)
    {
            var data = new List<List<int>>()
            {
                new List<int>(){1,2,3,4,5},
                new List<int>(){1,1,1,1,1}
            };
 
            using (var writer = new CsvWriter(@"hoge.csv"))
            {
                writer.Write(data);
            }
    }
}

関連記事

最後に… このブログに興味を持っていただけた方は、 ぜひ 「Facebookページ に いいね!」または 「Twitter の フォロー」 お願いします!!