C#でCSVファイルを簡単に読込む方法
CSV 形式の重要性
最近はテキストデータファイルというと、JSON とか XML などによるデータ交換というようなトピックが取り上げられることが多いです。 確かにウェブ上の API などでは JavaScript (ECMAScript) に簡単に取り込めるとか、WSDL からプロキシを自動生成できるとか、メリットは多いですね。
そうはいっても、特定のシステム間のデータ連携などでは、わざわざ JavaScript を介する意味もなければ、XML で型を誰でもわかるようにいちいち指定するのも無意味なことも多いので、 データ出力形式としては基本的な固定長データとかカンマ区切り、タブ区切りといったテキストデータが主役と言っていいと思います。
その意味で地味ながら、CSV ファイルを正しく読んで処理するというのは日常業務では大変重要な処理といえます。
意外と面倒な CSV 読み込み
ところが、カンマなどはデータそのものになりえます。
カンマをデータに含めるために、文字列を二重引用符で囲って、文字列の区切りを指定するということは良く行われますが、 今度は、じゃぁ二重引用符は本当にデータにならないの?とか、いろいろと面倒が起きるわけです。
※二重引用符をデータとするときは "通常" は、二重引用符を二つ重ねます。
さらに、一般的には改行文字もデータに入ったりします。
そのため「一行読んで、カンマでスプリットすればいいだけでしょ」というほど簡単ではありません。
安易に「自分のシステムではデータは単純なアルファニューメリックで済むから、カンマで区切れば十分」という人と、 「いやいや、ウチのシステムではカンマはたまにデータに入ってくるから単純に区切るとひどいことになるぞ」という人が、 軽々しくデータを交換したらエラーが多発という状況は目に見えています。
最終的にはそれぞれの実装に従わざるをえませんが、デファクト・スタンダードとしてのフォーマットとしては RFC4180 の記載が役に立ちます。
次で紹介する TextFieldParser は、私が知っている限り RFC4180 の内容をカバーしています。
TextFieldParser を利用して CSV ファイルを解析
前置きが長くなりましたが、C# で CSV ファイルを読むライブラリとしては、 Microsoft.VisualBasic に実装されている TextFieldParser を利用するのが便利です。
VB.Net 以下の実装ですが、C# でも使えます。
利用するには Microsoft.VisualBasic.dll の参照をプロジェクトに追加します。
その上で次のように、TextFieldParser を使って CSV ファイルを読むことができます。
using Microsoft.VisualBasic.FileIO;
using System;
class Program {
static void Main(string[] args) {
using(var parser = new TextFieldParser(@"C:\Test\car1.csv")) {
parser.Delimiters = new string[] { "," };
while(!parser.EndOfData) {
Console.WriteLine("-----");
var fields = parser.ReadFields();
foreach(var s in fields) {
Console.WriteLine($"{s}");
}
}
}
}
}
ここで、テスト用の CSV データファイルは次のように書いています。
1,"Toyota",Corolla,2017,"$18,500" 2,"Toyota",Prius,2017,"$23,475" 3,"Honda",Civic,2017,"$18,740"
実行結果は次のとおりです。
数字、二重引用符 (") で囲ったデータ、囲っていないデータ、カンマを含む文字列データなどを混ぜていますが、読み込めていますね。
尚、上のコードではデリミタ (区切り文字) として、カンマを指定しているので CSV として読み込んでいます。 もしここで、タブを区切り文字とすればタブ区切りデータも同様に読むことができます。(タブは "\t" です)