C# | 2週間で身につくアプリを作りながら学ぶC#の基本 - 9日目

C# C#
スポンサーリンク

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」という型として表現する
DateTimestring と同じように、自分で型を作る
配列ではなく「Result のリスト」を扱うイメージをつかむ

といった、「C# らしさ」が一気に強くなる領域です。

「ログ 1 行を“オブジェクト”として扱う」方向に進めていくので、
9日目の内容がそのまま 10日目の土台になります。

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