C#で出●館インセンティブ情報を通知するbot作ってみた②
押忍!
某youtuberの登場キャラでおなじみ残心ニキこと「鎖骨打ちのサトJ」です!
前の記事
の冒頭で書いたように燃え尽き症候群になってたわけですが
そんな中出た試合の動画がアップされましたw
自分の試合は
1回戦が16:40~
2回戦が56:30~
です。
1回戦の試合見れば残心ニキなのがわかると思いますw
あと
当然優勝はできませんでしたw
この試合はフルコンタクト系団体で最大手の一角である新極真会の
シニア全日本的な感じの大会でした
つまりシニアデビュー戦です
シニアなんでサポーターありの試合なんですが最後にサポーターありの試合に出たのが高校2年生の時なんで14年ぶりのフル装備での試合になります
久しぶりにフル装備で試合したけどヘッドガード息苦しすぎる、、、
ヘッドガード+飛沫防止フェイスシールドなんで秒でガス欠しましたw
似たような構造のヘッドガードをしながら組技、寝技までやる空道の選手を改めてすごいなって思いました
ってわけで本題に
今日のテーマは前回の記事のフローチャートのこの部分
の解説です。
■そもそもなんでCSVにしたか
可変の値を使うときにどのようにデータを渡すかを考えた場合以下の案が浮かびました
DB
Configファイル
コマンドライン引数
CSVあるいはテキストファイル
まず1は維持費とかの問題で速攻却下。詳しい理由はこの記事で書いてます
2はXML形式で書くことになるがこのツールを普及させると考えてXMLは一般曹にはなじみ薄いので却下
3に関しても一般ユーザーから見れば難しいかもだし、渡した後のデータ加工が難しそうだったので消去法で4にしました
CSVのサンプルはこんな感じです
1行目はひな形で各列に入力する項目を記載してます
2行目以降は実際に通知する地域の値を入力します
A列は地域、B列は都道府県、C列は市区町村です
写真はCSVファイルをエクセルで開いた例ですが
メモ帳とかで開く場合は「関東,東京都,千代田区」って感じでカンマ区切りで入力します
■CSVファイルの読み取り方
ここからは実際にコードで説明していきます
C#やVB.NETでファイル読み取りによく使われるのがStreamReaderクラスです
大変便利なのですがこのStreamReaderクラスだと以下の場合だとうまく機能しません
要素内にカンマや改行が含まれている時
CSVがダブルクォート(「""」)で囲まれている形式だった場合
今回の場合だとあまり気にしなくてもいいことですが、ユーザーは何するかわかりません。あらゆるケースを想定しないといけないです。
(機能の実装はできて当たり前。バリデーションなどエラーチェックなどの配慮がちゃんとできるかどうかが腕の見せ所だと先輩から習いました)
なので今回はStreamReaderクラスではなくTextFieldParserクラスを使うことにしました。TextFieldParserクラスを使うことで上記問題が解消できます
使い方はStreamReaderと似てますがこちらはそのままじゃ使えないので
Microsoft.VisualBasic.FileIOをインポートさせる必要があります
using Microsoft.VisualBasic.FileIO;
宣言の仕方はこんな感じです
var txtParser = new TextFieldParser([読み取るファイルのフルパス]);
TextFieldParserクラスはIDisoisableインターフェースを継承してるのでusingで宣言してあげると実装が楽です
IDisoisableやusingが不明な方はこちら見てください
TextFieldParserを宣言した後はまずは区切り文字を設定します。
今回はカンマ区切りなので引数には「,」を設定します
txtParser.SetDelimiters(",");
あとはループ処理で1行ずつ読み取って値をListなどに格納していきます
var ret = new List<string[]>();
txtParser.SetDelimiters(",");
//一行目はヘッダー
txtParser.ReadFields();
while (!txtParser.EndOfData)
{
string[]? value = txtParser.ReadFields();
if (value != null)
{
ret.Add(value);
}
}
ヘッダーの値はいらないのでループ処理をする前に一度ReadFieldsを書くことでループスタート地点を2行目からにしております
string[]? value = txtParser.ReadFields();
ReadFieldsで一行ずつ読み取って結果を文字列配列で取得するわけですが
ReadFieldsには少しめんどくさい挙動があります
ReadFieldsは対象の行のフィールドが空の行の場合にNullを返します
なんでReadFieldsを使うときはNullチェックはしたほうがいいです。
他の対策としてはReadLineで文字列として取得した後にString.Splitを使って文字列配列にするなどがあります
終わりに
いかがだったでしょうか
自分も実は普段StreamReaderを使っており今回作るにあたってTextFieldParserは初めて知りました。
今後使っていきたいと思います。
次回は実際に出前館インセンティブサイトをスクレイピングしていきます
この記事が気に入ったらサポートをしてみませんか?