3 * Copyright (C) 2005, uguu All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
36 /// <see cref="TextWriter"/> インスタンスに CSV 形式のデータを出力します。
39 /// インスタンスの作成時に指定した改行文字、区切り文字を使用して CSV データを出力します。
40 /// 出力する値に改行文字、区切り文字、ダブルクォーテーションが含まれる場合、エスケープして出力します。
41 /// null 参照や <see cref="DBNull.Value"/> 値は空文字列として出力します。
43 public sealed class CsvWriter : IDisposable
48 private TextWriter writer;
52 private string newLine;
56 private string delimiter;
60 private int columnIndex = 0;
64 private int rowIndex = 0;
66 /// 指定した <see cref="TextWriter"/> インスタンスに CSV 形式のデータを出力する、
67 /// <see cref="CsvWriter"/> クラスの新しいインスタンスを初期化します。
68 /// 改行文字は <see cref="Environment.NewLine"/> 、区切り文字は "," になります。
70 /// <param name="writer">出力先ライター。</param>
71 /// <exception cref="ArgumentNullException"><paramref name="writer"/> 引数が null 参照の場合。</exception>
72 public CsvWriter(TextWriter writer) : this(writer, Environment.NewLine, ",")
76 /// 指定した <see cref="TextWriter"/> インスタンスに指定した改行文字と区切り文字で CSV 形式のデータを出力する、
77 /// <see cref="CsvWriter"/> クラスの新しいインスタンスを初期化します。
79 /// <param name="writer">出力先ライター。</param>
80 /// <param name="newLine">改行文字。</param>
81 /// <param name="delimiter">区切り文字。</param>
82 /// <exception cref="ArgumentNullException">
83 /// <paramref name="writer"/> 引数が null 参照の場合。
84 /// <paramref name="newLine"/> 引数、 <paramref name="delimiter"/> 引数が null 参照か空文字列の場合。
86 public CsvWriter(TextWriter writer, string newLine, string delimiter)
91 throw new ArgumentNullException("writer");
93 if (newLine == null || newLine == string.Empty)
95 throw new ArgumentNullException("newLine");
97 if (delimiter == null || delimiter == string.Empty)
99 throw new ArgumentNullException("delimiter");
102 this.writer = writer;
103 this.newLine = newLine;
104 this.delimiter = delimiter;
107 /// <see cref="CsvWriter"/> インスタンスを閉じます。
112 if (this.writer != null)
119 /// <see cref="CsvWriter"/> インスタンスを閉じます。
122 public void Dispose()
124 if (this.writer != null)
131 /// <see cref="CsvWriter"/> インスタンスが閉じているかどうかを取得します。
137 return (this.writer == null);
141 /// 現在の出力列位置を表すインデックス番号を取得します。
146 public int ColumnIndex
150 return this.columnIndex;
154 /// 現在の出力行位置を表すインデックス番号を取得します。
163 return this.rowIndex;
169 /// <param name="value">出力する値。</param>
170 /// <exception cref="ObjectDisposedException"><see cref="CsvWriter"/> インスタンスが既に閉じている場合。</exception>
171 public void Write(string value)
173 // インスタンスの状態をチェックします。
176 throw new ObjectDisposedException("writer");
183 value = string.Empty;
185 if (value.IndexOf(this.newLine) != -1 || value.IndexOf(this.delimiter) != -1)
187 v += value.Replace("\"", "\"\"");
194 if (this.columnIndex > 0)
196 v = this.delimiter + v;
198 this.writer.Write(v);
204 /// <exception cref="ObjectDisposedException"><see cref="CsvWriter"/> インスタンスが既に閉じている場合。</exception>
205 public void WriteNewLine()
207 // インスタンスの状態をチェックします。
210 throw new ObjectDisposedException("writer");
214 this.writer.Write(this.newLine);
215 this.columnIndex = 0;
221 /// <param name="values">出力する値の配列。</param>
222 /// <exception cref="ArgumentNullException"><paramref name="values"/> 引数が null 参照の場合。</exception>
223 /// <exception cref="ObjectDisposedException"><see cref="CsvWriter"/> インスタンスが既に閉じている場合。</exception>
224 public void Write(string[] values)
229 throw new ArgumentNullException("values");
232 foreach (string value in values)
240 /// <param name="values">出力する値の二次元配列。</param>
241 /// <exception cref="ArgumentNullException"><paramref name="values"/> 引数が null 参照の場合。</exception>
242 /// <exception cref="ObjectDisposedException"><see cref="CsvWriter"/> インスタンスが既に閉じている場合。</exception>
244 /// <see cref="Write(string[])"/> メソッドは複数の値を連続して出力しますが、 <see cref="Write(string[][])"/> メソッドは複数行を出力します。
245 /// 出力は必ず新しい行から始まります。
246 /// 既に何らかの値が出力されている場合、改行してから出力を開始します。
247 /// 一行ごとに (当然ですが) 改行します。
249 /// したがって、全ての出力が完了すると、出力位置は新しい行の先頭になります。
251 public void Write(string[][] values)
256 throw new ArgumentNullException("values");
258 foreach (string[] line in values)
262 throw new ArgumentNullException("values");
266 if (this.columnIndex > 0)
270 foreach (string[] line in values)
272 foreach (string value in line)
280 /// リーダーから値を読み込み、全て出力します。
282 /// <param name="dataReader">値の読み込み元リーダー。</param>
283 /// <exception cref="ArgumentNullException"><paramref name="dataReader"/> 引数が null 参照の場合。</exception>
284 /// <exception cref="ObjectDisposedException"><see cref="CsvWriter"/> インスタンスが既に閉じている場合。</exception>
286 /// <see cref="IDataReader"/> インスタンスから全ての列の値を取得し、全ての行を出力します。
287 /// 出力は必ず新しい行から始まります。
288 /// 既に何らかの値が出力されている場合、改行してから出力を開始します。
289 /// 一行ごとに (当然ですが) 改行します。
291 /// したがって、全ての出力が完了すると、出力位置は新しい行の先頭になります。
292 /// 全ての出力が完了しても <see cref="IDataReader"/> インスタンスは閉じられません。
294 public void Write(IDataReader dataReader)
296 this.Write(dataReader, null, int.MaxValue);
299 /// リーダーから値を読み込み、指定した列、及び行数を出力します。
301 /// <param name="dataReader">値の読み込み元リーダー。</param>
302 /// <param name="names">
304 /// 全ての列を出力する場合は null 参照を指定することができます。
306 /// <param name="count">出力する行数。</param>
307 /// <exception cref="ArgumentNullException"><paramref name="dataReader"/> 引数が null 参照の場合。</exception>
308 /// <exception cref="ArgumentException"><paramref name="count"/> 引数が 0 未満の場合。</exception>
310 /// <see cref="IDataReader"/> インスタンスから指定した順番で列の値を取得し、指定した行数の行を出力します。
311 /// 出力は必ず新しい行から始まります。
312 /// 既に何らかの値が出力されている場合、改行してから出力を開始します。
313 /// 一行ごとに (当然ですが) 改行します。
315 /// したがって、全ての出力が完了すると、出力位置は新しい行の先頭になります。
316 /// 全ての出力が完了しても <see cref="IDataReader"/> インスタンスは閉じられません。
318 public void Write(IDataReader dataReader, string[] names, int count)
321 if (dataReader == null)
323 throw new ArgumentNullException("dataReader");
327 throw new ArgumentException("count 引数が 0 未満です。");
330 if (this.columnIndex > 0)
334 for (int row = 0; row < count; row++)
336 if (!dataReader.Read())
340 object[] values = null;
343 values = new object[names.Length];
344 for (int nameIndex = 0; nameIndex < names.Length; nameIndex++)
346 values[nameIndex] = dataReader[names[nameIndex]];
351 values = new object[dataReader.FieldCount];
352 dataReader.GetValues(values);
354 foreach (object value in values)
356 if (value == DBNull.Value)
358 this.Write(string.Empty);
360 else if (value == null)
362 this.Write(string.Empty);
366 this.Write(value.ToString());