プロが教える店舗&オフィスのセキュリティ対策術

駆け出しの初心者です。
以前c言語を少々勉強していてcsvファイルの読み込み、書き出しを練習していたのですが、最近c#を使うようになり、その便利さに圧倒されております。

今回c#で読み込みたいcsvファイルは以下のようになっております
"abc","123","あいうえお"

ただのカンマ区切りであれば読み込みは簡単ですが、
上記のようにダブルクオーテーションでそれぞれの文字列が囲まれている場合に文字列だけを読み込み、配列に代入していくのに何かスムーズな方法はありませんでしょうか?


ちなみに現在単純にカンマ区切りのcsvファイルを読み込むコードを
書いた所ですので、載せておきます
これをいじってスムーズにいければうれしいのですが、いかがでしょうか?

private void LoadData()
{
string path = "Data.csv";
string delimStr = ",";//区切り文字
char[] delimiter = delimStr.ToCharArray();
string[] strData;//分解後の文字用変数
string strLine;//1行分のデータ
Boolean fileExists = System.IO.File.Exists(path);
if (fileExists)
{
System.IO.StreamReader sr = new System.IO.StreamReader(
path,
System.Text.Encoding.Default);
while (sr.Peek() >= 0)
{
strLine = sr.ReadLine();
strData = strLine.Split(delimiter);
DataSet.DataTable.AddDataTableRow(
DateTime.Parse(strData[0]),
strData[1],
   strData[2],
int.Parse(strData[3]),
strData[4]);
}

sr.Close();
}


}


いつも丁寧な回答で協力してくれる皆様には心から感謝しております。
どうぞよろしくお願いします。

A 回答 (3件)

こう応用するとよいです。


以下に全コードを載せておきますが、ポイントはこの一行です。
strData = strLine.Split(delimiter);

strData = CsvToArrayList1(strLine)[0];


private void LoadData() {
string path = "Data.csv";
string[] strData;//分解後の文字用変数
string strLine;//1行分のデータ
Boolean fileExists = System.IO.File.Exists(path);
if(fileExists) {
System.IO.StreamReader sr = new System.IO.StreamReader(path,System.Text.Encoding.Default);
while(sr.Peek() >= 0) {
strLine = sr.ReadLine();
strData = CsvToArrayList1(strLine)[0];//変更点
DataSet.DataTable.AddDataTableRow(
DateTime.Parse(strData[0]),
strData[1],
strData[2],
int.Parse(strData[3]),
strData[4]);
}

sr.Close();
}
}


//参照先<http://dobon.net/vb/dotnet/file/readcsvfile.html
//参照先だとArrayListを返し値にしていますが使いづらいので、List<string[]>に変更しています。
public static System.Collections.Generic.List<string[]> CsvToArrayList1(string csvText) {
System.Collections.Generic.List<string[]> csvRecords =
new System.Collections.Generic.List<string[]>();

//前後の改行を削除しておく
csvText = csvText.Trim(new char[] { '\r', '\n' });

//一行取り出すための正規表現
System.Text.RegularExpressions.Regex regLine =
new System.Text.RegularExpressions.Regex(
"^.*(?:\\n|$)",
System.Text.RegularExpressions.RegexOptions.Multiline);

//1行のCSVから各フィールドを取得するための正規表現
System.Text.RegularExpressions.Regex regCsv =
new System.Text.RegularExpressions.Regex(
"\\s*(\"(?:[^\"]|\"\")*\"|[^,]*)\\s*,",
System.Text.RegularExpressions.RegexOptions.None);

System.Text.RegularExpressions.Match mLine = regLine.Match(csvText);
while(mLine.Success) {
//一行取り出す
string line = mLine.Value;
//改行記号が"で囲まれているか調べる
while((CountString(line, "\"") % 2) == 1) {
mLine = mLine.NextMatch();
if(!mLine.Success) {
throw new ApplicationException("不正なCSV");
}
line += mLine.Value;
}
//行の最後の改行記号を削除
line = line.TrimEnd(new char[] { '\r', '\n' });
//最後に「,」をつける
line += ",";

//1つの行からフィールドを取り出す
System.Collections.Generic.List<string> csvFields =
new System.Collections.Generic.List<string>();
System.Text.RegularExpressions.Match m = regCsv.Match(line);
while(m.Success) {
string field = m.Groups[1].Value;
//前後の空白を削除
field = field.Trim();
//"で囲まれている時
if(field.StartsWith("\"") && field.EndsWith("\"")) {
//前後の"を取る
field = field.Substring(1, field.Length - 2);
//「""」を「"」にする
field = field.Replace("\"\"", "\"");
}
csvFields.Add(field);
m = m.NextMatch();
}

csvFields.TrimExcess();
csvRecords.Add(csvFields.ToArray());

mLine = mLine.NextMatch();
}

csvRecords.TrimExcess();
return csvRecords;
}

/// <summary>
/// 指定された文字列内にある文字列が幾つあるか数える
/// </summary>
/// <param name="strInput">strFindが幾つあるか数える文字列</param>
/// <param name="strFind">数える文字列</param>
/// <returns>strInput内にstrFindが幾つあったか</returns>
public static int CountString(string strInput, string strFind) {
int foundCount = 0;
int sPos = strInput.IndexOf(strFind);
while(sPos > -1) {
foundCount++;
sPos = strInput.IndexOf(strFind, sPos + 1);
}

return foundCount;
}
    • good
    • 1
この回答へのお礼

ご丁寧な解説に心から感謝いたします。

頂いたコードをそのまま貼り付けた後、自分好みに調整し、
見事目的が達成されました。

本当に嬉しかったです、ありがとうございました。

お礼日時:2010/03/27 10:54

本気でCSVを読もうと思ったら、C#もCも同じですね。


一文字ずつ判断するよりないです。

Microsoft.VisualBasicの名前空間のほうになら、便利な関数もあるみたいですが。
http://www.atmarkit.co.jp/fdotnet/dotnettips/487 …
    • good
    • 0
この回答へのお礼

わかりやすい解説ページの紹介ありがとうございます。
是非参考にさせていただきます。

お礼日時:2010/03/27 09:55

http://dobon.net/vb/dotnet/file/readcsvfile.html
が参考になりますか?

この回答への補足

お返事ありがとうございます、
拝見させていただきましたがまだまだ初心者の為、このコードをどう応用したらよいのかが想像できません…

もうちょっと勉強してから見直してみたいと思います。
ありがとうございました。

補足日時:2010/03/22 19:46
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!