はじめに
過去記事「【C#】csvファイルをバイナリデータで取り込むプログラム」で作成したサンプルプログラムをもとに、CSVやtxtファイルをバイナリーデータでまるごと取り込めるプログラムを作成した。
過去記事URL:https://qiita.com/kohi7777/items/40b9c78ee3ff4de43468
変更点
1.機能を分け、親クラスと子クラスに分割した。
2.取得できるデータをバイナリーデータか文字列か選べるようにした。
3.メソッド間でやりとりしてたバイナリーデータ配列の型をArrayListではなくコレクションクラスに変えて使いやすくした。
4.コンマで分割する機能は一旦削除。
入力csvデータ
1,りんご,赤
2,バナナ,黄
3,メロン,緑
4,もも,ピンク
サンプルプログラム
親クラス(計算処理クラス)
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;
}
}
}
子クラス(実行用メソッドクラス)
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クラス(使い方サンプル)
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,もも,ピンク