C#(Dotnet)でCSVファイルを扱う

C#(Dotnet)でCSVファイルを扱う

C#(Dotnet)でCSVファイルを扱う

以前、C#でCSVファイルを読み込むにて、C#(dotnet)でCSVファイルを読み込む方法を紹介していました。
前回からの改良点や、追加した部分を紹介していこうと思います!

なおGitには最新のコードやdllを配置しているので、よかったら見てみてください。
「こうするべきでは?」というのがあれば連絡もらえると嬉しいです!
https://github.com/flying-YT/CSV4net/tree/master


読み込みクラスの改良点

以前のコードでは値をそのまま配列に格納していましたが、ダブルクォーテーションで囲われている場合はダブルクォーテーションを含めて配列格納していました。
しかし、実際には値はダブルクォーテーションを含まず取り出したいケースがあると思い、囲っているダブルクォーテーションを削除するように仕様変更しています。
具体的な変更点としては、下記配列を格納する部分で正規表現を使っています。

  • 変更前
  • var strArray = new string[separateList.Count];
    foreach (var item in separateList.Select((value, index) => new { value, index }))
    {
        strArray[item.index] = item.value;
    }
                
  • 変更後
  • var strArray = new string[separateList.Count];
    foreach (var item in separateList.Select((value, index) => new { value, index }))
    {
        Match m = Regex.Match(item.value, "\"(?(.|\\r\\n)*?)\"");
        if(m.Success)
        {
            strArray[item.index] = m.Groups["data"].Value;
        }
        else
        {
            strArray[item.index] = item.value;
        }
    }
                

今まではforeach分の中で、そのまま配列に格納していましたが、
正規表現を使い、ダブルクォーテーションで囲われた文字列を検知するようにしています。
グループ化もしているので、マッチする場合にはダブルクォーテーションの中身のみを取り出し、配列格納するように修正しています。
マッチしない場合はダブルクォーテーションで囲われていないデータになるので、以前同様にそのまま配列格納しています。

ダブルクォーテーションで囲う場合は、改行を含んでいるケースが多いので、任意の文字列または改行を検知できるようにしています。


なお、上記改行コードは「\n」のみのケースもあるのでは?と思うかもしれませんが、データ読み込み中に下記コードを追加しているので、改行コードは「\r\n」確定になります。
先ほどのダブルクォーテーション処理も反映させたコードは下記です。

  • 変更前
  • if(!isDoubleQuotation)
    {
        separateList.Add(sb.ToString());
        sb = new StringBuilder();
        var strArray = new string[separateList.Count];
        foreach (var item in separateList.Select((value, index) => new { value, index }))
        {
            strArray[item.index] = item.value;
        }
        separateList = new List();
        returnList.Add(strArray);
    }
                
  • 変更後
  • if(isDoubleQuotation)
    {
        sb.Append("\r\n");
    }
    else
    {
        separateList.Add(sb.ToString());
        sb = new StringBuilder();
    
        var strArray = new string[separateList.Count];
        foreach (var item in separateList.Select((value, index) => new { value, index }))
        {
            Match m = Regex.Match(item.value, "\"(?(.|\\r\\n)*?)\"");
            if(m.Success)
            {
                strArray[item.index] = m.Groups["data"].Value;
            }
            else
            {
                strArray[item.index] = item.value;
            }
        }
        separateList = new List();
        returnList.Add(strArray);
    }
                


CSVファイルの書き込みクラス

今までは、CSVファイルの読み込みのクラスを作成していましたが、CSVファイルで出力したいケースも存在するかと思います。
そのため、新たに書き込み用クラスのWritingFileを作成しました。

ファイル出力の際に、ダブルクォーテーションをつけて出力するか、つけないかの選択ができるようにしています。
ただし、改行コードを含む場合は強制的にダブルクォーテーションをつけてその値を書き込みます。

引数にはstring型の配列を値とするListと、出力先のフォルダパスになります。
また、値をダブルクォーテーションで囲うかを判定するためのbool値も引数に含んでいます。デフォルトは囲わない形式です。
その他には、区切り文字や文字コードの指定をすることが可能です。

public static void WriteCSV(List list, string path, bool isDoubleQuotation=false, char separate=',', string encoding="utf-8")
{
    List writeList = new List();
    foreach (string[] strArray in list)
    {
        StringBuilder sb = new StringBuilder();
        foreach(string str in strArray)
        {
            if(isDoubleQuotation)
            {
                sb.Append("\"" + str + "\"" + separate);
            }
            else
            {
                if(str.Contains("\r\n") || str.Contains("\n"))
                {
                    sb.Append("\"" + str + "\"" + separate);
                }
                else
                {
                    sb.Append(str + separate);
                }
            }
        }
        string text = sb.ToString();
        writeList.Add(text.Remove(text.Length - 1));
    }
    WriteFile(writeList, path, encoding);
}
        

WriteFileメソッドは下記になります。

public static void WriteFile(List list, string path, string encoding="utf-8")
{
    using(StreamWriter sr = new StreamWriter(path, false, Encoding.GetEncoding(encoding)))
    {
        foreach(string str in list)
        {
            sr.WriteLine(str);
        }
    }
}
        

以上がCSVファイルの出力クラスです。


さいごに

このような形でdotnet用のCSV操作ライブラリを作成しています。
自分自身、仕事中のログ分析で結構活用しています。
もしよければ、使ってみての感想や、不具合などあれば連絡いただけると嬉しいです。
自分自身でも使いながらデバック・改善をしていきますので、引き継ぎよろしくお願いいたします。

コメント

このブログの人気の投稿

PowerAppsで座席表を作成する

Power AutomateでTeamsのキーワードをトリガーにする

Power Automateで文字列抽出