【C#】CSVの読み込みロジックを簡単解説(項目中のカンマ、改行対応)

プログラミングTips
この記事は約4分で読めます。

C#を使ったCSVの読み込み方法に関する検索が多いようなので、今回はそれを取り上げたいと思います。

このブログで紹介した以前の記事では、Microsoft.VisualBasic.dll を参照設定することで使える「TextFieldParser」を用いたサンプルを紹介しました。

今回はそのような参照設定は必要なく、C#のコードだけでCSV読み込みを行っています。

勿論、ダブルクォーテーションで括られている項目の中に、カンマや改行キーが入っていても正しく分解できるようにしています。

また、関数化していますので、そのままコピー&ペーストでお使いいただけます。

中身の理解を助けるためのフローチャートも載せていますので、是非参考にしてください。

アルゴリズムの解説

CSVの仕様を把握しておく必要がありますが、詳しくは こちら の記事に委ねるとして、それを踏まえると基本的な考え方は次様になります。

  1. ファイルから1文字づつ読み込む
  2. カンマが見つかったら、そこまでを1項目として認識する
  3. 改行が見つかったら、そこまでを1行として認識する
  4. ダブルクォーテーションが見つかれば、次のダブルクォーテーションが見つかるまでの間は、カンマや改行は単なる文字として扱う
  5. ダブルクォーテーションが項目内に2個連続して登場する場合、ダブルクォーテーション1つに置き換える

項目内にカンマや改行が無い場合

項目内にカンマや改行が無い場合は非常に簡単です。

もし、行数が数百万行くらいで、項目の中にカンマや改行が無く、ダブルクォーテーションで括られていなければ、一気にメモリに読み込んでカンマで分割するという方法が使えます。

実際にはこのような形式のCSVも多いので、簡易的ではありますが実用的です。

ちなみに、ファイルを読み込むためのクラスを使っているので、ソースコードの冒頭に次の参照設定を記述しておいて下さい。

ファイル名を指定すると、CSVを読み込んで、文字列配列のリスト(List<string[])で返すようになっています。

参考までに、foreach ループを linq に換えたサンプルも掲載しておきます。

項目内にカンマや改行がある場合

こちらが今回の記事の本命です。

ファイル名と文字のエンコード名を渡すと、CSVを分割して List<string[]>で返す仕様なのですが、ダブルクォーテーションが見つかると、次のダブルクォーテーションが見つかるまでの間、カンマがあっても分割せず、改行があっても改行しないようにする必要があります。

そのため、次の3つの変数を用意しています。

  • ファイルを1文字づつ読み込んでカンマが見つかると、そこまでを1つの項目として切り出して格納する value 変数
  • 改行が見つかるまで、切り出した項目を1行分だけ蓄えておく line 変数
  • 改行が見つかったら、line変数を次々と追加していく result 変数

ファイルから取り出した1文字が、ダブルクォーテーションとダブルクォーテーションの間にあるものか否かを区別するため、bool 型の dq_flg というフラグを用意しました。

ダブルクォーテーションが見つかると 、フラグの状態を反転させるという動作をさせることで、ダブルクォーテーション内か否かを区別しています。

これを前提にしたフローチャートは次の様になります。

以上で前置きは終了です。

では、実際のソースコードを見ていきましょう。

ソースコード

少し長くなりましたが、全体のソースコードは次の様になります。

これもコピー&ペーストで張り付けて使えるようにしています。

StreamReader クラスを使っていますので、 冒頭の参照設定に using System.IO; を追加しておいて下さい。

まとめ

今回はCSV読み込みをC#のロジックだけで実現する方法を、図式で解説しました。

サンプルソースはそのまま使えますが、中身を理解していれば好きなように改造できますので、例えばカンマではなくタブ区切り対応するとか、色々と手を加えても面白いと思います。

タイトルとURLをコピーしました