C# でテキストファイルを手軽に読み書き

2020年1月21日

C#、使っていますか?

Windows 上でちょっとしたテキストファイルを取り扱いたいと思ったとき、C# は凄まじい効率性を発揮します。そのためだけでも、C# を覚えてみる価値はありますよ。

ここではその一端として、CSV ファイルを取り扱う C# のコードを紹介します。

はじめに

ここでの CSV ファイルは、厳密な仕様に準拠したものではない、単純なものを想定していることをお断りしておきます。

なお、ファイル読み書き関連のクラスを利用するために、コードの冒頭に次の using 宣言を追記しておいてください。

using System.IO;

CSV を解析したい場合

1. テキストファイルを読む

次のコード例は、エンコード形式が Shift-JIS のファイルを想定したものです。

string path = @"C:\test.csv";
var encoding = Encoding.GetEncoding("shift_jis");
string[] lines = File.ReadAllLines(path, encoding);

ReadAllLines 関数は強力です。上のコードを実行し終えたときには、すでにすべての文字列が配列に収まっています。ファイルのオープン・クローズなどの煩雑な処理は不要です。

ファイルパスには制御文字 '\’ が含まれることが多いので、文字列リテラルに '@’ を付加して制御文字を無視することをおすすめします。

2. 一行ずつ処理する

ファイルの中身はすでに配列になっていますから、foreach 文を使えばその一行一行を取り出すループが書けます。

foreach (string line in lines)
{
  /* line を使った処理をここに書く */
}

私はこのように配列の名前を複数形にしておいて、foreach を使って単数形で受けるスタイルが好きです。迷いなく書けて可読性も高いので、おすすめです。

3. 文字列を分割する

C# には Split というこれまた強力な関数があります。カンマで区切られた文字列を分割したければ、次のように書きます。

string[] cells = line.Split(',');

この関数は文字列関数の中でも特に使う場面が多いので、要チェックです。

まとめ

これまでのコードをまとめると、次のようになります。

string[] lines = File.ReadAllLines(@"C:\test.csv", Encoding.GetEncoding("shift_jis"));
foreach (string line in lines)
{
  string[] cells = line.Split(',');
  /* cells[0], cells[1] ... を使った処理をここに書く */
}

これだけです。CSV のパース処理を自前で書こうとしたことのある人は特に、この恐ろしいほどの効率性が理解できるのではないかと思います。

CSV を作成したい場合

1. 文字列を結合する

複数の文字列をカンマ区切りで結合するには、Join 関数を使います。

string[] cells = { "alpha", "beta", "gamma", "delta" };

string line = string.Join(",", cells);

これも使用頻度が高く、覚えるべき関数の一つです。

2. 一行ずつ追加する

サイズ未定の配列を作りたい場合、C# では List を使います。

var lines = new List<string>();
lines.Add("0,1,2,3");
lines.Add("4,5,6,7");

結果的に Add が呼ばれた回数が、そのサイズになります。

3. テキストファイルを書く

WriteAllLines 関数を使えば、読み込みと同様、一撃で終わります。

string path = @"C:\test.csv";
var encoding = Encoding.GetEncoding("shift_jis");
File.WriteAllLines(path, lines, encoding);

まとめ

これまでのコードをまとめると、次のようになります。

var lines = new List<string>();
for (int i = 0; i < N; ++i)
{
  var cells = new string[4];
  /* cells[0], cells[1] ... を作る処理をここに書く */
  lines.Add(string.Join(",", cells));
}
File.WriteAllLines(@"C:\test.csv", lines, Encoding.GetEncoding("shift_jis"));

上のコードを応用すれば、だいたいどのような CSV ファイルでも思うがままに作れます。ぜひ、試してみてください。