developer's diary

最近はc#のエントリが多いです

【改善】C# (dotnetcore) CSVファイルを永続化に利用したコンソールアプリを改善

本エントリは以下の解答をもう一歩改善した内容

mitsugeek.net

前回の、「カンマを含められない」、「Main関数の行数が多い」を改善。

解答(ソース)

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using CsvHelper;
using CsvHelper.Configuration;

namespace csvExample
{
    /// <summary>
    /// 行オブジェクト
    /// </summary>
    internal class CsvRow
    {
        public string name { get; set; }
        public string telNo { get; set; }
    }

    /// <summary>
    /// CSVと行オブジェクトのマッピング
    /// </summary>
    internal class CsvTable : ClassMap<CsvRow>
    {
        private CsvTable()
        {
            Map(c => c.name).Index(0);//0番目
            Map(c => c.telNo).Index(1);//1番目
        }
    }


    class Program
    {
        //メモリ上の住所録データ
        private static List<CsvRow> Rows = new List<CsvRow>();

        //CSVファイルのパス
        private const string CSV_PATH = @"data.csv";

        static void Main(string[] args)
        {
            //CSVファイルを読み込む
            ReadCsv();

            while (true) {
                //コマンドの一覧を表示
                Console.WriteLine("Command:list or add or init or exit");

                //コマンドの入力を求める
                string command = Console.ReadLine();

                if(command == "list") List();
                else if(command == "add") Add();
                else if(command == "init") Init();
                else if (command == "exit") break;
            }
        }

        /// <summary>
        /// 一覧表示
        /// </summary>
        static void List()
        {
            foreach (var row in Rows)
            {
                //メモリ上の内容を表示
                Console.Write("name:[");
                Console.Write(row.name);
                Console.Write("] telno:[");
                Console.Write(row.telNo);
                Console.WriteLine("]");
            }
        }

        /// <summary>
        /// 追加
        /// </summary>
        static void Add()
        {
            //追加の場合

            //追加する内容の読み込み
            Console.WriteLine("name?");
            string name = Console.ReadLine();
            Console.WriteLine("telno?");
            string telno = Console.ReadLine();

            //メモリに追加
            Rows.Add(new CsvRow() { name = name, telNo = telno });

            //ファイルに書き込む
            WriteCsv();
        }

        /// <summary>
        /// 初期化
        /// </summary>
        static void Init()
        {

            //初期化の場合
            if (System.IO.File.Exists(CSV_PATH))
            {
                System.IO.File.Delete(CSV_PATH);
                Rows = new List<CsvRow>();
            }
        }

        /// <summary>
        /// CSV書き込み
        /// </summary>
        static void WriteCsv()
        {
            using (var writer = new StreamWriter(CSV_PATH))
            using (var csv = new CsvWriter(writer, CultureInfo.CurrentCulture))
            {
                csv.Configuration.HasHeaderRecord = false;
                csv.Configuration.RegisterClassMap<CsvTable>();
                csv.WriteRecords(Rows);
            }
        }

        /// <summary>
        /// CSV読み込み
        /// </summary>
        static void ReadCsv()
        {
            //ファイルが無い場合は何もしない
            if (!System.IO.File.Exists(CSV_PATH)) return;

            using (var reader = new StreamReader(CSV_PATH))
            using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
            {
                csv.Configuration.HasHeaderRecord = false;
                csv.Configuration.RegisterClassMap<CsvTable>();
                Rows.AddRange(csv.GetRecords<CsvRow>());
            }
        }
    }
}

各項目の解説

ここでの項目は、プロパティやメソッドのことを表しています。 それぞれ、以下のような役割があります。

項目 説明
CsvRow csvの項目を指定したPOCO(Plain Old CLR Object )
CsvTable csvの項目とクラスの項目のマッピング
Rows CSVから読み込んだデータを保持する領域。データを追加した場合、ここに追加される
CSV_PATH CSVファイルのパス
Main プログラムのエントリポイント。
初期処理で、ReadCSVを実行し、
その後はlist、add、init、exitのコマンドを受け付け、各コマンドに合わせた処理を行っている
List 一覧表示処理
Add 項目追加処理
Init データ初期化処理
WriteCsv Rowsの内容をCSVファイルに保存する関数
ReadCsv CSVファイルを読み込み、内容をRowsに設定する関数