9日目のゴールとテーマ
9日目のテーマは「“記録”を少しだけ本格的にする」です。
8日目で、診断結果をファイルに保存して「履歴」を持てるようになりました。
今日はそこから一歩進めて、
- 日付と時刻も一緒に保存する
- 1 回分の診断を“1 行”として記録する
- 履歴を読み込んで、1 行ずつきれいに表示する
という「ログっぽい記録」を扱っていきます。
ここから先は、アプリ開発でよく出てくる「ログ」「履歴」「記録」の考え方に直結します。
「1回の診断」を1行で表現する発想
8日目の保存方法の振り返り
8日目では、診断結果をこんな感じのテキストにして保存していました。
=== 診断結果 ===
「はい」と答えた数: 3 / 5
あなたはバランスタイプです。
家で過ごす時間も、外で過ごす時間も、どちらも楽しめるタイプです。
これをそのまま history.txt に追記していく形でした。
これは「読み物」としては分かりやすいですが、
「機械的に扱う」には少し扱いづらい形です。
例えば、
- 何回診断したか数えたい
- いつ診断したかを一覧にしたい
- 「インドアタイプだけ」を抽出したい
といったことをやろうとすると、テキストの解析が大変になります。
ログっぽく「1行で1件」を記録する
そこで、9日目では「1 回の診断を 1 行で表現する」形にしてみます。
例えば、こんな形式です。
2026-03-02 19:30,3/5,BALANCE
2026-03-03 08:15,5/5,INDOOR
この 1 行には、次の情報が入っています。
- 診断した日時
- 「はい」の数 / 質問数
- 判定結果のコード(BALANCE / INDOOR など)
こうしておくと、後からプログラムで読み込んで、
「日付ごとに集計」「タイプごとの件数」などがやりやすくなります。
日付と時刻を取得する
DateTime.Now を使う
C# では、現在の日時は DateTime.Now で取得できます。
DateTime now = DateTime.Now;
Console.WriteLine(now);
C#そのまま表示すると、環境によっては
2026/03/02 19:44:10
のような形式で出てきます。
ToString でフォーマットを指定する
ログとして保存するときは、形式を自分で決めておくと扱いやすくなります。
例えば、「年-月-日 時:分」の形にしたいなら、こう書きます。
DateTime now = DateTime.Now;
string timestamp = now.ToString("yyyy-MM-dd HH:mm");
Console.WriteLine(timestamp);
C#これで、
2026-03-02 19:44
のような文字列になります。
ここでのポイントは、フォーマット文字列です。
- yyyy → 4 桁の年
- MM → 2 桁の月
- dd → 2 桁の日
- HH → 24 時間表記の時
- mm → 分
この「フォーマットを決めて文字列にする」感覚は、
日付を扱うときにとてもよく使います。
判定結果を「コード」として表現する
テキストではなく「短いコード」にする理由
8日目の診断結果は、こんな感じの文章でした。
あなたはバランスタイプです。
家で過ごす時間も、外で過ごす時間も、どちらも楽しめるタイプです。
これをそのままログに入れてもいいのですが、
ログとしては「短くて機械的に扱いやすい形」の方が便利です。
そこで、判定結果を次のようなコードにしてみます。
- 超アクティブタイプ → ACTIVE
- バランスタイプ → BALANCE
- インドアタイプ → INDOOR
この「コード」をログに保存しておき、
画面に表示するときはコードを見て文章に変換する、という形にします。
判定ロジックからコードを返すメソッド
8日目の ShowResult は、yesCount から直接文章を表示していました。
これを少し変えて、「コードを返す」メソッドを作ります。
static string GetTypeCode(int yesCount, int total)
{
if (yesCount <= 1)
{
return "ACTIVE";
}
else if (yesCount <= 3)
{
return "BALANCE";
}
else
{
return "INDOOR";
}
}
C#これで、
string typeCode = GetTypeCode(yesCount, total);
C#のようにして、判定結果を短いコードとして扱えるようになります。
1行ログの文字列を組み立てる
「日時,はいの数/質問数,タイプコード」の形式
ここまでの要素を組み合わせて、
1 行分のログ文字列を作るメソッドを書いてみます。
static string BuildLogLine(int yesCount, int total)
{
DateTime now = DateTime.Now;
string timestamp = now.ToString("yyyy-MM-dd HH:mm");
string typeCode = GetTypeCode(yesCount, total);
string line = timestamp + "," + yesCount + "/" + total + "," + typeCode;
return line;
}
C#このメソッドの中でやっていることを整理すると、
- 現在時刻を取得して、決まった形式の文字列にする
- yesCount と total からタイプコードを求める
- 「日時,スコア,タイプコード」をカンマ区切りでつなげる
という流れです。
例えば、yesCount = 3, total = 5 のとき、BuildLogLine はこんな文字列を返します。
2026-03-02 19:50,3/5,BALANCE
これをそのままファイルに 1 行として書き込めば、
「1 回分の診断ログ」が完成です。
ログファイルに1行ずつ追記する
AppendAllText でログを増やしていく
8日目と同じく、File.AppendAllText を使います。
string logLine = BuildLogLine(yesCount, questions.Length);
File.AppendAllText("log.txt", logLine + Environment.NewLine);
C#ここでのポイントは、最後に Environment.NewLine を足していることです。
Environment.NewLineは「環境に合った改行コード」- Windows でも他の環境でも、適切な改行になる
これで、log.txt はこんな感じで増えていきます。
2026-03-02 19:30,3/5,BALANCE
2026-03-03 08:15,5/5,INDOOR
2026-03-04 21:10,1/5,ACTIVE
ログを読み込んで「履歴一覧」として表示する
ReadAllLines で1行ずつ読む
今度は、log.txt を読み込んで、
1 行ずつ「いつ・どんな結果だったか」を表示してみます。
static void ShowLogHistory()
{
string fileName = "log.txt";
if (!File.Exists(fileName))
{
Console.WriteLine("まだログはありません。");
Console.WriteLine();
return;
}
string[] lines = File.ReadAllLines(fileName);
Console.WriteLine("=== ログ履歴 ===");
for (int i = 0; i < lines.Length; i++)
{
string line = lines[i];
string[] parts = line.Split(',');
if (parts.Length != 3)
{
continue;
}
string timestamp = parts[0];
string scorePart = parts[1];
string typeCode = parts[2];
string typeLabel = ConvertTypeCodeToLabel(typeCode);
Console.WriteLine(timestamp + " " + scorePart + " " + typeLabel);
}
Console.WriteLine("=== ここまで ===");
Console.WriteLine();
}
C#ここでの重要ポイントを順番に見ていきます。
ReadAllLines の役割
File.ReadAllLines(fileName) は、
- ファイルを開く
- 各行を 1 つの要素として string[] にして返す
というメソッドです。
lines[0] が 1 行目、lines[1] が 2 行目…という形になります。
Split(‘,’) でカンマ区切りを分解する
line.Split(',') は、文字列をカンマで分割して配列にします。
例えば、
string line = "2026-03-02 19:30,3/5,BALANCE";
string[] parts = line.Split(',');
C#とすると、
parts[0]→"2026-03-02 19:30"parts[1]→"3/5"parts[2]→"BALANCE"
というふうに分かれます。
コードをラベルに変換する
ConvertTypeCodeToLabel は、
“BALANCE” を「バランスタイプ」のような日本語に変換するメソッドです。
static string ConvertTypeCodeToLabel(string typeCode)
{
switch (typeCode)
{
case "ACTIVE":
return "超アクティブタイプ";
case "BALANCE":
return "バランスタイプ";
case "INDOOR":
return "インドアタイプ";
default:
return "不明なタイプ";
}
}
C#これで、ログの 1 行を
2026-03-02 19:30 3/5 バランスタイプ
のように、読みやすい形で表示できます。
9日目の全体像を言葉でまとめる
アプリの流れ
9日目のアプリの流れは、こんな感じになります。
アプリ起動
ログ履歴(log.txt)があれば ShowLogHistory で一覧表示
質問に答えて yesCount を集計(7日目と同じ)
BuildLogLine で 1 行分のログ文字列を作る
AppendAllText で log.txt に追記する
(必要なら、8日目のように詳細な結果も別ファイルに保存する)
これで、
- 「人間向けの詳細な診断結果」(history.txt)
- 「機械的に扱いやすいログ」(log.txt)
という 2 種類の記録を持つアプリになります。
9日目のまとめ
今日のキーワードを整理します。
DateTime.Now と ToString
現在時刻を取得し、決まった形式の文字列に変換する。
1 行 1 件のログ
「日時,スコア,タイプコード」のように、1 行で 1 回分の情報を表現する。
File.ReadAllLines
ファイルを 1 行ずつ読み込んで string[] にする。
Split
区切り文字(ここではカンマ)で文字列を分割して、配列にする。
コードとラベルの分離
ログには短いコード(ACTIVE / BALANCE / INDOOR)を保存し、
画面表示のときに日本語ラベルに変換する。
ここまで来ると、「ただ動くだけのアプリ」から
「履歴を持ち、ログも残す“ちゃんとしたアプリ”」に近づいています。
次回(10日目)への予告
10日目は、いよいよ「クラス」と「オブジェクト」という考え方に入っていきます。
診断結果そのものを「Result」という型として表現するDateTime や string と同じように、自分で型を作る
配列ではなく「Result のリスト」を扱うイメージをつかむ
といった、「C# らしさ」が一気に強くなる領域です。
「ログ 1 行を“オブジェクト”として扱う」方向に進めていくので、
9日目の内容がそのまま 10日目の土台になります。
