CSVファイルを出力するファイルを作成したので、掲載しておきます。基本的にある程度仕様どおりのような気がしますが、間違っていたらご指摘ください。
CSVファイルの仕様(原文)
- http://www.ietf.org/rfc/rfc4180.txt
CSVファイルの一般的書式 (RFC4180 日本語訳)
- http://www.kasai.fm/wiki/rfc4180jp
動作環境
- 確認環境 Windows Vista
- 開発環境 Visual Studio 2008 Professional
- .NET 2.0以上
1.CSVWriterクラスの定義
CSVWriterを定義します。ソースは次の通り。今のクラスでは、ダブルクオーテーションで囲む場合、フィールド内のダブルクオーテーションをエスケープする処理が抜けていたりするので、足りない部分は適当に修正して使います。
using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Data; namespace CSVReaderWriter { /// <summary> /// CSVライター /// </summary> class CSVWriter : IDisposable { /// <summary>出力ストリーム</summary> StreamWriter _writer = null; #region コンストラクタ /// <summary> /// 指定されたストリームにデフォルトのエンコーディングで /// 出力を行います。 /// </summary> /// <param name="stream"></param> public CSVWriter(Stream stream) { _writer = new StreamWriter(stream, Encoding.Default); } /// <summary> /// 指定されたストリームに指定されたエンコーディングで /// 出力を行います。 /// </summary> /// <param name="stream"></param> /// <param name="encoding"></param> public CSVWriter(Stream stream, Encoding encoding) { _writer = new StreamWriter(stream, encoding); } /// <summary> /// 指定されたパスにデフォルトエンコーディングで /// 出力を行います。 /// </summary> /// <param name="path"></param> public CSVWriter(String path) { _writer = new StreamWriter(path, false, Encoding.Default); } /// <summary> /// 指定されたパスに指定されたエンコーディングで /// 出力を行います。 /// </summary> /// <param name="path"></param> /// <param name="encoding"></param> public CSVWriter(String path, Encoding encoding) { _writer = new StreamWriter(path, false, encoding); } #endregion #region プロパティ private bool _isTokenEnclosedWithDQuotas = false; /// <summary> /// フィールドがダブルクオーテーションで囲まれるかのプロパティ /// trueの場合ダブルクオーテーションで囲まれる /// </summary> public bool IsTokenEnclosedWithDQuotas { get { return _isTokenEnclosedWithDQuotas; } set { _isTokenEnclosedWithDQuotas = value; } } private string _separator = "\t"; /// <summary> /// 項目間の区切り文字 /// </summary> public string Separator { get { return _separator; } set { _separator = value; } } #endregion #region メソッド /// <summary> /// CSV出力ストリームに1行分出力する /// </summary> /// <param name="tokens"></param> protected void WriteLine(string[] tokens) { for (int i = 0; i < tokens.Length; ++i) { _writer.Write(DQuote(tokens[i])); if (i != tokens.Length - 1) { _writer.Write(Separator); } } _writer.Write("\n"); } /// <summary> /// トークンを必要に応じてダブルクオーテーションで加工する。 /// </summary> /// <param name="token"></param> /// <returns></returns> protected virtual string DQuote(string token) { bool needDQuote = IsTokenEnclosedWithDQuotas; if (token.Contains(Separator) || token.Contains("\r") || token.Contains("\n")) { needDQuote = true; } if (needDQuote) { token = token.Replace("\"", "\"\""); token = "\"" + token + "\""; } return token; } public void Flush() { _writer.Flush(); } public void Close() { if (_writer != null) _writer.Close(); } /// <summary> /// sourceに指定されている内容でCSVファイルを /// 出力します。列はsourceの列順に出されます。 /// </summary> /// <param name="source"></param> public virtual void WriteOnce(DataTable source) { List<int> list = new List<int>(); for (int i = 0; i < source.Columns.Count; ++i) { list.Add(i); } WriteOnce(source, list); } /// <summary> /// sourceに指定されている内容でCSVファイルを出力します。 /// 出力する列はcolumnOrderの順に出力されます。 /// </summary> /// <param name="source"></param> /// <param name="columnOrder"></param> public virtual void WriteOnce(DataTable source, IList<int> columnOrder) { foreach (DataRow row in source.Rows) { List<string> list = new List<string>(); foreach (int colIdx in columnOrder) { list.Add(row[colIdx].ToString()); } WriteLine(list.ToArray()); } } #endregion #region IDisposable Members public virtual void Dispose() { Close(); if (_writer != null) _writer.Dispose(); } void IDisposable.Dispose() { this.Dispose(); } #endregion } }
説明は以上です。次回の俺式CSVReaderのサンプルに動作例を掲載します。
指摘点とうがあればご連絡ください。
さんのコメント: さんのコメント: