はじめに
最近関わったプロジェクトで出くわしたCSV処理について、備忘の意味も込めて書きます。
恐らく今時こんな書き方をしている箇所を見ることはないだろうけど、参考までに。
何をしたかったのか
内容はいたってシンプルで、システムの既存機能として存在しているCSV取り込み
に手を加えるというもの。
具体的には、CSVのフォーマットが変わって、取り込むデータが1列増えたので対応する。
既存のCSVはA列、B列、C列、D列
というフォーマットだが、今回はB列とC列の間にBα列を追加
したいとのこと。
ソース
メソッド名等々は適当にぼかしてあります。
usingMicrosoft.VisualBasic.FileIO;// ...略privatevoidLoadCsv(stringcsvPath){// TextFieldParserでCSVを読み込みTextFieldParserparser=newTextFieldParser(csvPath,Encoding.GetEncoding("shift_jis"));parser.TextFieldType=FieldType.Delimited;parser.SetDelimiters(",");while(parser.EndOfData==false){string[]datas=parser.ReadFields();intcols=datas.length;// 列数が不正だったら終了if(cols!=4){return;}// A列処理if(string.IsNullOrEmpty(datas[0])){// ...略}// B列処理if(string.IsNullOrEmpty(datas[1])){// ...略}// C列処理if(string.IsNullOrEmpty(datas[2])){// ...略}// D列処理if(string.IsNullOrEmpty(datas[3])){// ...略}// 取得したデータをDBに書き込んだり...// その結果を画面に表示させたり...}}
ぼく「うわぁ・・・、まじかよ・・・」
見ての通り取り込むCSVのフォーマットに合わせてインデックスをハードコーディングしてあるので、先に書いた通りB列とC列の間にBα列を追加
するとなると、C列はdatas[2]
ではなくdatas[3]
になり、D列は・・・
といった風に、Bα列以降のインデックスをインクリメントしないといけなくなってくる。
もっと言うと、合計列数は4から5になるので列数不正となる条件はif(cols != 4)
からif(cols != 5)
になる。
まだ元々のフォーマットが4列だったから良かったものの、もしこれが10数列もあったら・・・と考えるとゾッとする。
というわけで、以下のようにCSVのインデックスをenum
で持たせることにしました。
// 列のインデックス定義privateenumCsvCols{// A列ColA=0,// B列ColB=1,// Bα列ColBalpha=2,// C列ColC=3,// D列ColD=4}// 列数privatestaticintCSV_COLS=Enum.GetNames(typeof(CsvCols)).Length;
そんでもって、各インデックスのハードコーディング箇所を以下のように修正
// 列数が不正だったら終了(修正前)//if(cols != 4){// return;//}// 列数が不正だったら終了(修正後)if(cols!=CSV_COLS){return;}// A列処理(修正前)//if(string.IsNullOrEmpty(datas[0])){// // ...略//}// A列処理(修正後)if(string.IsNullOrEmpty(datas[(int)CsvCols.ColA])){// ...略}
おわりに
これなら今後対象となるCSVのフォーマットが変わっても、enumの中身を変える(追加・削除する)だけで対応できます。
もしかしたらもっといいやり方があるのかもしれない(あったら教えてください)