トップ回答者
カンマ交じりの文のあるデータをCSVにする

質問
回答
-
http://ja.wikipedia.org/wiki/Comma-Separated_Values
// 参照元のRFC4180自体、そのまま従うと日本語を記述できない残念仕様ですが……。
- 編集済み Hongliang 2013年7月14日 3:23 リンク追加
- 回答の候補に設定 Jitta 2013年7月15日 11:37
- 回答としてマーク AzuleanMVP, Moderator 2013年7月15日 22:14
-
改行コードやデリミタ(コンマのような区切り文字)がフィールド値の中にあったり、改行コードが異なったり(例: Windows は CR + LF、Unix は LF)するのに対応する場合、フィールド値をダブルクォート (") で囲むと言った約束を設けて対応します。
が、そのような CSV ファイルの処置が可能なパーサーを自力で作るのは簡単ではありませんので、既存のパーサーを使うのがよさそうです。
http://surferonwww.info/BlogEngine/post/2010/10/28/CSV-parser.aspx
CSV パーサー- 回答の候補に設定 Jitta 2013年7月15日 11:36
- 回答としてマーク AzuleanMVP, Moderator 2013年7月15日 22:14
すべての返信
-
http://ja.wikipedia.org/wiki/Comma-Separated_Values
// 参照元のRFC4180自体、そのまま従うと日本語を記述できない残念仕様ですが……。
- 編集済み Hongliang 2013年7月14日 3:23 リンク追加
- 回答の候補に設定 Jitta 2013年7月15日 11:37
- 回答としてマーク AzuleanMVP, Moderator 2013年7月15日 22:14
-
改行コードやデリミタ(コンマのような区切り文字)がフィールド値の中にあったり、改行コードが異なったり(例: Windows は CR + LF、Unix は LF)するのに対応する場合、フィールド値をダブルクォート (") で囲むと言った約束を設けて対応します。
が、そのような CSV ファイルの処置が可能なパーサーを自力で作るのは簡単ではありませんので、既存のパーサーを使うのがよさそうです。
http://surferonwww.info/BlogEngine/post/2010/10/28/CSV-parser.aspx
CSV パーサー- 回答の候補に設定 Jitta 2013年7月15日 11:36
- 回答としてマーク AzuleanMVP, Moderator 2013年7月15日 22:14
-
> お礼を忘れておりました。
お礼は結構ですから、先のレスをどこまで理解したか、不明な点があれば何かを書いて下さい。そのようにして、お互い理解しあいながら進めていかないと、掲示板ではなかなか話が通じません。
最初の質問に対しては、先の自分のレス「改行コードやデリミタ(コンマのような区切り文字)がフィールド値の中にあったり、改行コードが異なったり(例: Windows は CR + LF、Unix は LF)するのに対応する場合、フィールド値をダブルクォート (") で囲むと言った約束を設けて対応します。」が十分回答になっていると思っています。
これが回答になっていない、もしくは内容が分からないということなら、具体的に何が不足か書いてもらわないと話が進められません。
いきなり別の質問に飛んでますが、そういうのは混乱を招くだけと思います。
-
理屈はある程度理解されたと思います。実装はTextFieldParser クラスを使うと便利です。
何故か Microsoft.VisualBasic.dll 内 にありますが、もちろん Visual C# Express Edition からも使えます。
ITmediaのTIPSにある以下の記事が解りやすいと思います。- 編集済み hihijiji 2013年7月15日 2:18 日本語修正
-
> ここは公開討論会の場だったのですね。
自分としては、MSDN フォーラムは、開発者同士の情報交換の場所と理解しています。なので、質問者と回答者だけ Q&A だけではなく、検索などでここを訪れた人の役にも立てればよりよいと思っています。
ただし、今回のやり取りは Q&A 目的だけでも問題ありと思いませんか? 例えば:
(1) いきなり「おかしなことになっていました。」とレスされましたが回答者には意味不明です。何がおかしいのですか?
(2) 「書き込みのときに、「,」を「","」に変える作業が必要」というのは、フィールドをダブルクォートで囲む手法として質問者さんが考えたことらしいと想像してますが、そうであれば「フィールドをダブルクォートで囲むことで対応するのは理解した。その手法として CSV ファイル作成時に「,」を「","」に変える作業が必要と解釈したが、それで間違いないか?」というように聞いてもらったほうが良いと思いませんか? (そうしてもらえたら「そうではありません。XXXのようにで行います・・・」と答えられたのですが。)
(3) 複数回答がありますが、誰の回答に対するレスなのかよく分からない。
(4) 結局、最終的に、どこまで理解していただいたのか分からない。
- 編集済み SurferOnWww 2013年7月15日 1:42 誤字訂正
-
その後、Webを検索しまくって、寝ずに考えて
class CsvFile
{
public string SaveInCsv(System.Data.DataTable dt, string csvPath)
{
System.Text.Encoding enc = System.Text.Encoding.GetEncoding("Shift_JIS");try
{
System.IO.StreamWriter sw = new System.IO.StreamWriter(csvPath, false, enc);int clmCount = dt.Columns.Count;
int lastClmIndex = clmCount - 1;// ヘッダー
for (int i = 0; i < clmCount; i++)
{
string field = dt.Columns[i].Caption;
if (field.IndexOf('"') > -1 ||
field.IndexOf(',') > -1 ||
field.IndexOf('\r') > -1 ||
field.IndexOf('\n') > -1 ||
field.StartsWith(" ") ||
field.StartsWith("\t") ||
field.EndsWith(" ") ||
field.EndsWith("\t"))
{
if (field.IndexOf('"') > -1)
field = field.Replace("\"", "\"\"");
field = "\"" + field + "\"";
}
sw.Write(field);
if (lastClmIndex > i)
sw.Write(',');
}
sw.Write("\r\n");foreach (System.Data.DataRow row in dt.Rows)
{
for (int i = 0; i < clmCount; i++)
{
string field = row[i].ToString();
if (field.IndexOf('"') > -1 ||
field.IndexOf(',') > -1 ||
field.IndexOf('\r') > -1 ||
field.IndexOf('\n') > -1 ||
field.StartsWith(" ") ||
field.StartsWith("\t") ||
field.EndsWith(" ") ||
field.EndsWith("\t"))
{
if (field.IndexOf('"') > -1)
field = field.Replace("\"", "\"\"");
field = "\"" + field + "\"";
}
sw.Write(field);
if (lastClmIndex > i)
sw.Write(',');
}
sw.Write("\r\n");
}
sw.Close();
}
catch (Exception ex)
{
return ex.Message;
}
return "";
}
}こんなコードにしましたら、書き込みがうまくいきました。
でも、データテーブルのヘッダー(タイトル)行が、IDで始まっていると、正しいCSVファイルにならないみたいでした。今はその原因を探っていますが、面倒なので、タイトル(上記のヘッダー部分)はすべてダブルクォーテーションで囲ってみようかと思っています。そうすると、うまくいくようです。
みなさんのご指導でうまくいってます。ありがとうございました。