C#でCSVを生成する際、ユーザがダイアログで指定した場所にうまく保存できません。
概要
下記のようなBuilderを記述の上、ユーザが指定した場所にCSVファイルを保存したいです。下記のようにすると、C:\Users\[ユーザ名]\Documents\Visual Studio 2013\Projects\[プロジェクト名]\[アプリ名]\bin\Debug
下には保存されるのですが、デスクトップ等ユーザが選択した場所に保存できません。
class CsvBuilder : IDisposable
{
/// <summary>
/// CSVファイルに書き込むストリーム
/// </summary>
private StreamWriter stream = null;
/// <summary>
/// ファイル名を指定して、 <see cref="CsvWriter">CsvWriter</see> クラスの新しいインスタンスを初期化します。
/// </summary>
/// <param name="path">書き込む完全なファイルパス。</param>
public CsvBuilder(string path) :
this(path, Encoding.Default)
{
}
/// <summary>
/// ファイル名、文字エンコーディングを指定して、 <see cref="CsvWriter">CsvWriter</see> クラスの新しいインスタンスを初期化します。
/// </summary>
/// <param name="path">書き込む完全なファイルパス。</param>
/// <param name="encoding">使用する文字エンコーディング。</param>
public CsvBuilder(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, string bankName, string extensiton)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.FileName = CreateDateTimeFileName(name, extension);
sfd.InitialDirectory = @"C:\";
sfd.Title = "ファイルの保存先を指定してください。";
sfd.Filter = "csv files (*.csv)|*.csv";
if (sfd.ShowDialog() == DialogResult.OK)
{
foreach (var row in data)
{
this.WriteRow<T>(row);
}
}
}
/// <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);
});
}
/// <summary>
/// 日付名のファイル名を返す
/// </summary>
/// <param name="extension">拡張子</param>
/// <returns>拡張子を含んだ、日付のファイル名</returns>
public static string CreateDateTimeFileName(string bankName, string extension)
{
return DateTime.Now.ToString("yyyyMMddhhmmss") + bankName + extension;
}
}
・ 使用する側のコードは下記のようなものです。
using (var csvBuilder = new CsvBuilder(CsvBuilder.CreateDateTimeFileName("Name", ".csv")))
{
csvBuilder.Write(list, "Name", ".csv");
}
動作環境
・.NET Frame Work 4.5
・Visual Studio2013
追加で…
Debugフォルダ下に作成されるCSVファイルは削除する処理を入れるべきものでしょうか?開発時の確認にはあった方が便利ですが、延々とたまっていくのをたまにまとめて削除という運用も微妙かと思っています。
よろしくお願いします。