0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2021-03-04

はじめに

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

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

変更点

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

入力csvデータ

test.csv
1,りんご,赤
2,バナナ,黄
3,メロン,緑
4,もも,ピンク

サンプルプログラム

親クラス(計算処理クラス)

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;
        }
    }
}

子クラス(実行用メソッドクラス)

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クラス(使い方サンプル)

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型で取得でき、GetLineDataConvertStringメソッドでは1行分を文字列に変換して取得できる。

出力結果

1,りんご,赤
2,バナナ,黄
3,メロン,緑
4,もも,ピンク
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?