diff --git a/TIASshot/Utils/IoUtil.cs b/TIASshot/Utils/IoUtil.cs
index 95f9d16..a731ece 100644
--- a/TIASshot/Utils/IoUtil.cs
+++ b/TIASshot/Utils/IoUtil.cs
@@ -131,18 +131,33 @@
}
///
- /// 設定値をCSVファイルに書き込む
+ /// 設定値をCSVファイルに書き込む.
+ /// 値(ユーザー入力のデータ名・保存フォルダのパス等)にカンマ・ダブルクォート・改行が
+ /// 含まれても行が崩れないよう,RFC 4180 に従ってクォートする(該当しない値は従来どおり).
///
///
///
public static void WriteInfo(StreamWriter sw, Dictionary info) {
sw.WriteLine($"撮影日時,{DateTime.Now:yyyy/MM/dd HH:mm:ss}"); // 撮影日時を追加
foreach (var kvp in info) {
- sw.WriteLine($"{kvp.Key},{kvp.Value}");
+ sw.WriteLine($"{EscapeCsvField(kvp.Key)},{EscapeCsvField(kvp.Value)}");
}
}
///
+ /// CSV の 1 フィールドを RFC 4180 に従ってエスケープする.
+ /// カンマ・ダブルクォート・CR・LF を含む場合のみ全体をダブルクォートで囲み,
+ /// 内部のダブルクォートを二重化する.それ以外はそのまま返す(null は空文字).
+ ///
+ /// フィールド値(null 可)
+ /// エスケープ済みのフィールド
+ private static string EscapeCsvField(string field) {
+ if (string.IsNullOrEmpty(field)) return "";
+ if (field.IndexOfAny(new[] { ',', '"', '\r', '\n' }) < 0) return field;
+ return "\"" + field.Replace("\"", "\"\"") + "\"";
+ }
+
+ ///
/// 効果音を再生する
///
///