【C#】CSVの読み込みと書き込みを部品化しました!

プログラミング入門
この記事は約7分で読めます。

DIYプログラミングにおいて、C#を使ったCSVファイルの読み込み、書き込みは結構需要があります。

Google検索すると、CSVファイルの解説や、C#による読み書きのプログラムのサンプル例はたくさん目にしますが、実際に使おうとすると、色々な事を考慮してプログラムを書き足す必要があります。

面倒なことは置いといて、「コピペして使えるソースコードがほしい!」という方のために、実用的なCSV読み込み、書き込みのサンプルをご紹介します。

サンプルと言っても、私が実際にDIYプログラミングで使っているものなので、必要と思われる一通りの機能は揃っています。

ちなみに、WindowsFormとWPFのどちらからでも利用可能です。

CSVファイルはDataTableと相性抜群

CSVファイルをプログラムから読み込みたい場合とは、読み込んだ結果に対して何らかの加工を加えたいからですよね。

例えば別のアプリに読み込ませられるようフォーマット変換するとか、特定のデータだけを除外したいとかです。

時には、加工した結果を再びCSVファイルとして保存することもあります。

この様なニーズに対応する上で一番扱いやすいのは、何といってもDataTable です。

CSVをDataTableに入れてあげると、特定の条件でフィルタリングしたり、特定の条件に一致する項目を加工したりする行為が格段にやり易くなります。

ですから、今回紹介するソースコードは、CSVを読み込んでDataTableとして返したり、DataTableの内容をCSVファイルとして出力できるようになっています。

プログラムの仕様

仕様は次の通りです。

CSV読み込み

  • 出力ファイル名の指定
  • ヘッダの有無の指定
  • 最大読み込み行数の指定
  • 文字列エンコードの指定
  • 区切り文字の指定(自動判定機能付き)

CSV書き込み

  • 出力ファイル名の指定
  • ヘッダの出力有無の指定
  • 区切り文字の指定
  • 文字列エンコードの指定
  • 既存ファイルへの追加指定

これらは引数として指定することができます。

最初に参照設定が必要

CSVファイルは、項目がカンマやタブで区切られているテキストファイルですが、項目をダブルクォートで囲むことにより、項目の中に改行やタブを含ませることが可能です。

また、改行やタブの有無に関係なく、ダブルクォートで囲ったり囲わなかったりと、色々なバリエーションが存在します。

1文字づつ自力で解析しても良いのですが、せっかくマイクロソフトが用意してくれているので、その機能を使わせて頂きます。

その為には、Microsoft.VisualBasic というアセンブリの参照設定が必要となります。

リファレンス

ネームスペースCommonClass
クラス名CsvUtil
機能CSVファイルの読み込み
メソッド名DataTable Read(filename, isHeader [ ,limit, encodeName,delimiter ])
戻り値の型DataTable
引数名内容省略時の初期値
stringfilename読み込みたいファイル名省略不可
boolisHeader1行目をヘッダとして解釈するか否かの指定省略不可
longlimit読み込み行数の制限値longの最大値
stringencodeNameエンコード文字の指定shift-jis
stringdelimiter区切り文字(1文字のみ指定可能)自動判定
(1行目に含まれるカンマとタブの数が多い方を採用)
機能CSVファイルの書き込み
メソッド名Write(dt, filename, writeHeader [ ,delimiter, encodeName ,isAppend ])
戻り値の型DataTable
引数名内容省略時の初期値
DataTabledtファイルに保存したDataTable省略不可
stringfilename書き込みたいファイル名ファイル名省略不可
boolisHeaderヘッダを出力するか否かの指定省略不可
stringdelimiter区切り文字(1文字のみ指定可能)カンマ
stringencodeNameエンコード文字の指定shift-jis
boolisAppend既にファイルが存在する場合、追加書き込みするか否かの指定追加しない
(上書する)

ソースコード

では、実際のソースコードを掲載します。

とりあえず説明は良いからコピペして使いたいという方は、どうぞ。

説明が必要な方は、ソースコードの後に解説します。

解説

コメントも出来るだけ入れるようにしていますので、ソースコードを見て頂ければ内容はほぼ理解できると思います。

用途によって必要な機能が違ってきますし、プログラムの書き方についても好みがあると思いますので、そこはどんどん自分の使いやすい様に追加・修正して頂ければ幸いです。

念のため、要点だけ簡単に解説しておきたいと思います。

TextFieldParser を使ってCSVを項目に分解

CSVを読み込んで区切り文字で分割する作業を、TextFieldParserというマイクロソフト標準のクラスで実現しています。

標準と言っても初めから組み込まれている訳では無いので、Microsoft.VisualBasic というアセンブリを参照し、またソースコード冒頭にも次の1行を入れています。

もし自力でやろうとするなら、1文字づつ解析しながら、ダブルクォートが見つかったら次に見つかるまでの間は、「改行」「タブ」「カンマ」を区切り文字として扱わないような工夫が必要です。

GetDelimiterで区切り文字を判定

引数の delimiter が省略されるか 空文字( “” )の場合、1行目を読み込んで区切り文字を判定しています。

方法は、カンマ(,) とタブコード(\t)の数を数えて、多い方を区切り文字として判断しているだけです。

1行目を使ってヘッダを作成

引数の isHeader が true の場合、1行目をヘッダと解釈し、DataColumnを作成しています。

この時のDataColumnの型は object 型になります。

もし厳密に型を合わせたいなら全データをスキャンしなければなりませんが、面倒なのでそこまではしていません。

isHeader が false の場合、列名を付けずに DataColumn を作成していますので、”Column1” のような列名が自動で作られます。

動的に列を追加

途中から列の数が変わるというケースは殆ど無いとは思いますが、私が扱うデータだとたまにあるので対応しました。

これは結構便利で、とりあえずカンマかタブで区切られていれば、少々いい加減なデータであっても、DataTableに収めることができます。

DataTableにさえ入ってしまえば、あとのデータ加工は楽ですからね。

CSV書き込みはダブルクォートの扱いに注意

書き込みの方は読み込みに比べて簡単です。

DataTableの内容を取り出し、セルの中にカンマやタブが含まれていたらダブルクォートで前後を括り、ファイル出力するだけです。

そのため、ダブルクォートで括る必要があるかを判断するローカル関数として enclose_ifneed というのを作っています。

まとめ

今回はCSVを読み込んでDataTableを返すメソッドと、DataTableの内容をCSVファイルに出力するメソッドを持った CsvUtil というクラスを作成し、そのソースコードを掲載しました。

ネームスペースが CommonClass としているのは、どのプロジェクトにも使える共通クラスとしての位置づけだからです。

今後とも、共通クラスはこのネームスペースで作っていきたいと思います。

今回の記事が皆さんのお役に立てれば光栄です。

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