Day 54 のゴールと全体像
Day 54 では、実務でもよく登場する 「CSV」 をテーマにしていきます。 今日のキーワードは次の4つです。
- CSVとは
- CSV読み込み
- CSV書き込み
- データ分割
ファイル操作を学んだ Day 53 の内容を一歩進めて、 「表形式のデータ」を扱えるようになるのが、今回のゴールになります。
Excel で開けるあのファイル、 家計簿や顧客リスト、商品一覧など、 現場で使われるデータの多くが CSV でやり取りされていることも多いので、 ここを押さえておくと一気に“実務感”が増してきます。
CSVとは何かをイメージする
「カンマ区切りのテキストファイル」
CSV は Comma Separated Values の略で、 直訳すると「カンマで区切られた値たち」という意味になります。
中身はただのテキストですが、 次のようなルールで書かれています。
- 1行が「1レコード(1件分のデータ)」
- 行の中で、カンマ
,で項目を区切る - 1列目が「ID」、2列目が「名前」、3列目が「メールアドレス」…といった形で、列ごとに意味を持たせる
たとえば、ユーザー情報の CSV はこんな感じです。
Id,Name,Email
1,山田太郎,yamada@example.com
2,佐藤花子,hanako@example.com
3,鈴木一郎,ichiro@example.com
見た目はただのテキストですが、 Excel で開くと「表」として表示される、 そんな“素朴だけれど便利なフォーマット”が CSV です。
CSVを書き込んでみる
まずは「ユーザー一覧」を CSV に出力する
Day 53 で学んだファイル書き込みの応用として、 ユーザー情報を CSV に書き出してみます。
using System;
using System.IO;
using System.Collections.Generic;
class User
{
public int Id { get; }
public string Name { get; }
public string Email { get; }
public User(int id, string name, string email)
{
Id = id;
Name = name;
Email = email;
}
}
class CsvWriteExample
{
public static void Run()
{
string folder = "data";
string filePath = Path.Combine(folder, "users.csv");
// フォルダがなければ作成
if (!Directory.Exists(folder))
{
Directory.CreateDirectory(folder);
}
// 書き出すユーザー一覧を用意
var users = new List<User>
{
new User(1, "山田太郎", "yamada@example.com"),
new User(2, "佐藤花子", "hanako@example.com"),
new User(3, "鈴木一郎", "ichiro@example.com")
};
// CSV の行を組み立てるためのリスト
var lines = new List<string>();
// 1行目はヘッダー(列名)
lines.Add("Id,Name,Email");
// 2行目以降にユーザー情報を書き込む
foreach (var user in users)
{
// カンマ区切りで 1 行の文字列を作る
string line = $"{user.Id},{user.Name},{user.Email}";
lines.Add(line);
}
// 行の一覧を CSV ファイルに書き込む
File.WriteAllLines(filePath, lines);
Console.WriteLine($"CSV ファイル '{filePath}' にユーザー一覧を書き込みました。");
}
}
C#ここでのポイントは次のとおりです。
- CSV は「1行=1レコード」「カンマ区切り」というルールで書かれます。
- 1行目にヘッダー(列名)を書いておくと、後で読み込むときにもわかりやすくなります。
List<string>に行ごとの文字列をためておき、File.WriteAllLinesでまとめて書き込むと、コードがすっきりします。
この users.csv は、実際に Excel で開いてみると、 きちんと表として表示されるはずです。 自分のコードが「現実のツールとつながる瞬間」は、ちょっと嬉しくなりますね。
CSVを読み込んでみる
書いたものを「オブジェクト」に戻す
次は、先ほど書き出した users.csv を読み込んで、 User クラスの一覧に復元してみます。
using System;
using System.IO;
using System.Collections.Generic;
class CsvReadExample
{
public static void Run()
{
string folder = "data";
string filePath = Path.Combine(folder, "users.csv");
if (!File.Exists(filePath))
{
Console.WriteLine($"CSV ファイル '{filePath}' が存在しません。先に書き込み処理を実行してください。");
return;
}
// CSV ファイルの全行を読み込む
string[] lines = File.ReadAllLines(filePath);
var users = new List<User>();
// 1行目はヘッダーなので、2行目から処理する
for (int i = 1; i < lines.Length; i++)
{
string line = lines[i];
// カンマで分割して、各列の値を取り出す
string[] columns = line.Split(',');
if (columns.Length < 3)
{
Console.WriteLine($"行 {i + 1} の列数が足りません。スキップします。");
continue;
}
// 列の順番に意味を持たせる(Id, Name, Email)
int id = int.Parse(columns[0]);
string name = columns[1];
string email = columns[2];
var user = new User(id, name, email);
users.Add(user);
}
Console.WriteLine("CSV から読み込んだユーザー一覧:");
foreach (var user in users)
{
Console.WriteLine($"Id: {user.Id}, Name: {user.Name}, Email: {user.Email}");
}
}
}
C#ここで押さえておきたいポイント:
File.ReadAllLinesで、CSV の各行を文字列配列として取得します。line.Split(',')で、カンマ区切りの文字列を「列ごとの配列」に分割します。- 列の順番(0番目が Id、1番目が Name、2番目が Email)を決めておくことで、 CSV とクラスの対応関係がはっきりします。
この「行を読み込んで、カンマで分割して、オブジェクトに変換する」という流れが、 CSV 読み込みの基本パターンになります。
データ分割の考え方をもう少し深掘りする
Split で分割するだけでは足りない場面
先ほどは line.Split(',') でシンプルに分割しましたが、 実務ではもう少し複雑な CSV に出会うこともあります。
たとえば、
1,"山田,太郎",yamada@example.com
のように、 名前の中にカンマが含まれているケースです。
この場合、単純に Split(',') すると、
"1""\"山田""太郎\"""yamada@example.com"
のように、意図しない分割になってしまいます。
本格的な CSV パーサーを自作するのは大変なので、 実務では 専用ライブラリ(CsvHelper など)を使うことが多いです。
ただ、入門段階では、
- 「カンマを含まない前提のシンプルな CSV」
- 「ダブルクォートなどのエスケープを考えなくてよい CSV」
を扱うところから始めるのが現実的です。
シンプルな CSV を前提にした分割テンプレート
入門用としては、次のようなテンプレートを覚えておくと便利です。
string line = "1,山田太郎,yamada@example.com";
// カンマで分割
string[] columns = line.Split(',');
// 列数チェック
if (columns.Length >= 3)
{
int id = int.Parse(columns[0]);
string name = columns[1];
string email = columns[2];
Console.WriteLine($"Id: {id}, Name: {name}, Email: {email}");
}
else
{
Console.WriteLine("列数が足りません。");
}
C#この形をベースにして、 列の数や型を変えながら、 自分の用途に合わせた CSV 読み込み処理を書いていくイメージです。
CSV を使ったミニ演習:商品一覧の読み書き
商品クラスを定義して、CSV で保存・読み込みする
最後に、Day 54 の内容をひとつにまとめたミニ演習として、 商品一覧を CSV で扱う例を紹介します。
using System;
using System.IO;
using System.Collections.Generic;
class Product
{
public int Id { get; }
public string Name { get; }
public decimal Price { get; }
public Product(int id, string name, decimal price)
{
Id = id;
Name = name;
Price = price;
}
}
class ProductCsvExample
{
private const string Folder = "data";
private static readonly string FilePath = Path.Combine(Folder, "products.csv");
// 商品一覧を CSV に書き込む
public static void WriteProducts()
{
if (!Directory.Exists(Folder))
{
Directory.CreateDirectory(Folder);
}
var products = new List<Product>
{
new Product(1, "ノートPC", 120000m),
new Product(2, "マウス", 2000m),
new Product(3, "キーボード", 5000m)
};
var lines = new List<string>();
// ヘッダー行
lines.Add("Id,Name,Price");
// データ行
foreach (var p in products)
{
string line = $"{p.Id},{p.Name},{p.Price}";
lines.Add(line);
}
File.WriteAllLines(FilePath, lines);
Console.WriteLine($"商品一覧を CSV ファイル '{FilePath}' に書き込みました。");
}
// CSV から商品一覧を読み込む
public static List<Product> ReadProducts()
{
var products = new List<Product>();
if (!File.Exists(FilePath))
{
Console.WriteLine($"CSV ファイル '{FilePath}' が存在しません。");
return products;
}
string[] lines = File.ReadAllLines(FilePath);
for (int i = 1; i < lines.Length; i++)
{
string line = lines[i];
string[] columns = line.Split(',');
if (columns.Length < 3)
{
Console.WriteLine($"行 {i + 1} の列数が足りません。スキップします。");
continue;
}
int id = int.Parse(columns[0]);
string name = columns[1];
decimal price = decimal.Parse(columns[2]);
products.Add(new Product(id, name, price));
}
return products;
}
public static void Run()
{
// 1. 書き込み
WriteProducts();
// 2. 読み込み
var products = ReadProducts();
Console.WriteLine("CSV から読み込んだ商品一覧:");
foreach (var p in products)
{
Console.WriteLine($"Id: {p.Id}, Name: {p.Name}, Price: {p.Price}円");
}
}
}
C#このコードを実行すると、
products.csvに商品一覧を書き込み- その CSV を読み込んで
Productオブジェクトの一覧に復元し - コンソールに商品一覧を表示する
という、一連の流れを体験できます。
「CSV ↔ オブジェクト」の往復ができるようになると、 外部データとの連携がぐっと身近に感じられるようになります。
Day 54 のまとめ
Day 54 では、
- CSV が「カンマ区切りのテキストファイル」であり、 表形式のデータをシンプルに表現するフォーマットであること
File.WriteAllLinesとFile.ReadAllLinesを使って、 CSV の読み書きを行う基本的な方法Split(',')を使ったデータ分割の考え方と、 列の順番に意味を持たせる設計の大切さ- 商品やユーザーなどのクラスと CSV を組み合わせて、 「現実的なデータ」を扱うミニ演習
を、具体的なコード例とともに学びました。
CSV は、
- 小さなツールから
- 実務のバッチ処理
- データ連携の仕組み
まで、幅広い場面で使われる“縁の下の力持ち”のような存在です。
ぜひ、
- 列を増やしてみる(住所や電話番号などを追加する)
- 読み込んだデータをフィルタして表示してみる
- 別の CSV に書き出してみる
といった小さな工夫を重ねながら、 CSV 操作の感覚を少しずつ自分のものにしていっていただければうれしいです。
