【C#】改良版：csvやテキストファイルをバイナリーデータで取り込むプログラム

#はじめに
過去記事「【C#】csvファイルをバイナリデータで取り込むプログラム」で作成したサンプルプログラムをもとに、CSVやtxtファイルをバイナリーデータでまるごと取り込めるプログラムを作成した。

過去記事URL:https://qiita.com/kohi7777/items/40b9c78ee3ff4de43468

#変更点
1.機能を分け、親クラスと子クラスに分割した。
2.取得できるデータをバイナリーデータか文字列か選べるようにした。
3.メソッド間でやりとりしてたバイナリーデータ配列の型をArrayListではなくコレクションクラスに変えて使いやすくした。
4.コンマで分割する機能は一旦削除。

#入力csvデータ
```test.csv
1,りんご,赤
2,バナナ,黄
3,メロン,緑
4,もも,ピンク
```

#サンプルプログラム
##親クラス(計算処理クラス)
```C#:CSVByteOperation_Base.cs
using System;
using System.Collections.Generic;

namespace test
{
    /// <summary>
    /// CSVバイト操作スーパークラス
    /// </summary>
    class CSVByteOperation_Base
    {
        /// <summary>
        /// バイト配列から位置、長さでバイト配列を取得する
        /// </summary>
        /// <param name="InputData">Byteデータ配列</param>
        /// <param name="StartPoint">開始ポイント</param>
        /// <param name="Length">取得したい長さ</param>
        /// <returns></returns>
        protected List<byte> GetByteFromByte(List<byte> InputData, int StartPoint, int Length)
        {
            List<byte> rtnValue;

            if (Length == 0)
                Length = InputData.Count - StartPoint;

            if (Length < 1)
            {
                rtnValue = new List<byte>();
                return rtnValue;
            }

            rtnValue = new List<byte>();

            for (int i = 0; i < Length; i++)
            {
                if (StartPoint + i < InputData.Count)
                    rtnValue.Add(InputData[StartPoint + i]);
            }

            return rtnValue;
        }

        /// <summary>
        /// テキストデータを読み込んでバイト配列を取得する
        /// </summary>
        /// <param name="FilePath">テキストデータのパス</param>
        /// <returns>List型</returns>
        protected List<byte> GetBinaryData(string FilePath)
        {
            List<byte> rtnValue = new List<byte>();

            System.IO.FileStream fs = null;
            System.IO.BinaryReader br = null;

            try
            {
                fs = new System.IO.FileStream(FilePath, System.IO.FileMode.Open);
                br = new System.IO.BinaryReader(fs);

                int Length = (int)fs.Length;

                var ForConvertion = br.ReadBytes(Length);
                fs.Close();

                foreach (var item in ForConvertion)
                {
                    rtnValue.Add(item);
                }
            }
            catch (Exception ex)
            {
                if (br != null)
                    br.Close();

                if (fs != null)
                    fs.Close();

                throw ex;
            }

            return rtnValue;
        }

        /// <summary>
        /// 改行を区切りとして、バイトデータを1行ずつまとめてリストに取得する
        /// </summary>
        /// <param name="InputData"></param>
        /// <returns></returns>
        protected List<List<byte>> DivideLine(List<byte> InputData)
        {
            List<List<byte>> rtnValue = new List<List<byte>>();

            int StartPoint = 0;
            int EndPoint = 0;
            int Length = 0;

            while (EndPoint >= 0)
            {
                EndPoint = SearchCRLF(InputData, StartPoint);

                if (EndPoint < 0)
                {
                    Length = InputData.Count - StartPoint;

                    if (Length <= 0)
                        break;
                }
                else
                    Length = EndPoint - StartPoint;

                var LineData = GetByteFromByte(InputData, StartPoint, Length);

                rtnValue.Add(LineData);

                StartPoint = EndPoint + 1;
            }

            return rtnValue;
        }

        /// <summary>
        /// 読み込みデータからCRLFの位置を取得
        /// </summary>
        /// <param name="InputData">バイト配列</param>
        /// <param name="StartPoint">開始ポイント</param>
        /// <returns></returns>
        protected int SearchCRLF(List<byte> InputData, int StartPoint)
        {
            int EndPoint = -1;

            for (int i = StartPoint; i < InputData.Count - 1; i++)
            {
                if (InputData[i] == 0xD & InputData[i + 1] == 0xA)
                {
                    EndPoint = i + 1;
                    break;
                }
            }

            return EndPoint;
        }
    }
}
```

##子クラス(実行用メソッドクラス)
```C#:CSVByteOperation_Method.cs
using System;
using System.Collections.Generic;

namespace test
{
    /// <summary>
    /// CSVバイト操作メソッドクラス
    /// </summary>
    class CSVByteOperation_Method : CSVByteOperation_Base
    {
        private string _FilePath;
        public List<List<byte>> _ByteList;

        /// <summary>
        /// コンストラクタ　CSVデータのByte変換とライン区切り
        /// </summary>
        /// <param name="FilePath"></param>
        public CSVByteOperation_Method(string FilePath)
        {
            try
            {
                _FilePath = FilePath;

                GetCSV();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// CSVデータのByte変換とライン区切り
        /// </summary>
        public void GetCSV()
        {
            try
            {
                _ByteList = new List<List<byte>>();

                var BinaryData = GetBinaryData(_FilePath);
                _ByteList = DivideLine(BinaryData);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 読み込んだバイナリーデータリストの行数を取得
        /// </summary>
        /// <returns></returns>
        public int GetDataCount()
        {
            try
            {
                if (_ByteList == null)
                    return 0;

                return _ByteList.Count;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 読み込んだバイナリーデータリストのi番目のラインを取得
        /// </summary>
        /// <param name="index">取得したいインデックス</param>
        /// <returns></returns>
        public List<byte> GetLineData(int index)
        {
            try
            {
                if (_ByteList == null)
                    return null;

                if (index >= _ByteList.Count)
                    return null;

                return _ByteList[index];
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 読み込んだバイナリーデータリストのi番目のラインを文字列で取得
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public string GetLineDataConvertString(int index)
        {
            try
            {
                if (_ByteList == null)
                    return null;

                if (index >= _ByteList.Count)
                    return null;

                var ByteArray = new byte[_ByteList[index].Count];

                for (int i = 0; i < _ByteList[index].Count; i++)
                {
                    ByteArray[i] = _ByteList[index][i];
                }

                return System.Text.Encoding.Default.GetString(ByteArray);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
}
```

##Programクラス(使い方サンプル)
```C#:Program.cs
using System;
using static System.Console;

namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
            CSVByteOperation_Method csvm = new CSVByteOperation_Method(@"C:\Folder\test.csv");

            for (int i = 0; i < csvm.GetDataCount(); i++)
            {
                WriteLine(csvm.GetLineDataConvertString(i));
            }

            ReadKey();
        }
    }
}
```

#使い方解説
インスタンスを生成するときに、引数にファイルパスを入れる。
すると、コンストラクタでファイルをバイナリーデータに変換し、リストに保持する。
上の使い方サンプルのように、GetDataCountメソッドでループの回数を設定する。
GetLineDataメソッドではバイナリーデータの配列を1行分List<Byte>型で取得でき、GetLineDataConvertStringメソッドでは1行分を文字列に変換して取得できる。

#出力結果
```
1,りんご,赤
2,バナナ,黄
3,メロン,緑
4,もも,ピンク
```