delete from hateblo.jp where 1=1;

タイトルに意味はありません。

CSVファイル関連の拡張

脳内コンパイル。すなわち、未コンパイルのため、コンパイルエラーが出るかも。
抽象クラスでの実装を試みた。

処理概要としては、以下のことを行う。
指定された型のArrayListCSVファイルを読み込みながら作成。
指定された型のArrayListCSVファイルを書き込み。

もう少し拡張を行うとしたら、ヘッダー行の対応。(以下のソースは未対応)

エラーがあったので修正しておきます。

参考にしたのは以下のページ。すばらしい。
DataTableや配列等をCSV形式のファイルとして保存する - .NET Tips (VB.NET,C#...)
CSV形式のファイルをDataTableや配列等として取得する - .NET Tips (VB.NET,C#...)

using System.Text.RegularExpressions;
using System.Collections;
using System.IO;
using System.Text;

class CSVFile<T>
{
	private string _csvFile;
	private bool _isTrimEachRecord = false;
	private string _writeEncoding = "Shift_JIS";
	/// <summary>
	/// 読み込み時クォーテーション除去後のトリミングを行うかどうか
	/// </summary>
	protected bool IsTrimingEachRecord
	{
		get	{	return _isTrimEachRecord;	}
		set	{	_isTrimEachRecord = value;	}
	}
	/// <summary>
	/// 書き込み時のエンコード種別
	/// </summary>
	protected string WriteEncoding
	{
		get	{	return _writeEncoding;	}
		set	{	_writeEncoding = value;	}
	}
	/// <summary>
	/// 指定された型からArrayList型へ変換。
	/// 継承先(具体クラス)でArrayList型の領域は確保してください。
	/// </summary>
	/// <param name="item">指定された型</param>
	/// <return>ArrayList型(string)</return>
	virtual protected ArrayList ConvertStructure(T item)
	{
		return null;
	}
	/// <summary>
	/// ArrayList型から指定された型へ変換。
	/// 継承先(具体クラス)で指定された型の領域は確保してください。
	/// </summary>
	/// <param name="item">ArrayList型(string)</param>
	/// <return>指定された型</return>
	virtual protected T ConvertStructure(ArrayList item)
	{
		return default(T);
	}
	
	/// <summary>
	/// CSVファイルパスを保持
	/// </summary>
	/// <param name="csvFile">CSVファイルパス</param>
	virtual public CSVFile(string csvFile)
	{
		_csvFile = csvFile;
	}
	
	/// <summary>
	/// CSVをArrayListに変換
	/// </summary>
	/// <returns>変換結果のArrayList</returns>
	virtual public ArrayList ReadCSV()
	{
		char[] TrimChars = {
			'\r', '\n'
		};
		
		ArrayList csvRecords = new ArrayList();

		// 読み込みストリームを開く 
		StreamReader _sr = new StreamReader(_csvFile,Encoding.GetEncoding(WriteEncoding),true);

		//1行のCSVから各フィールドを取得するための正規表現
		Regex regCsv = new Regex("\\s*(\"(?:[^\"]|\"\")*\"|[^,]*)\\s*,",RegexOptions.None);

		ArrayList csvFields = new ArrayList();
		string line;
		//一行ずつ取り出す
		while ((line = _sr.ReadLine()) != null)
		{
			// ArrayListを初期化 
			csvFields.Clear();
			//改行記号が"で囲まれているか調べる
			while ((CountString(ref line, "\"") % 2) == 1)
			{
				string nextLine = _sr.ReadLine();
				// 読み込みすぎた場合は例外を発生させる 
				if (nextLine == null)
				{
					throw new  System.IO.EndOfStreamException();
				}
				line += nextLine;
			}
			//行の最後の改行記号を削除し「,」をつける
			line = line.TrimEnd(TrimChars) + ",";

			//1つの行からフィールドを取り出す
			Match m = regCsv.Match(line);
			while (m.Success)
			{
				//前後の空白を削除
				string field = m.Groups[1].Value.Trim();
				//"で囲まれている時
				if (field.StartsWith("\"") && field.EndsWith("\""))
				{
					//前後の"を取る
					field = field.Substring(1, field.Length - 2);
					//「""」を「"」にする
					field = field.Replace("\"\"", "\"");
				}
				//Trimを行う設定かどうかを判定する 
				if (IsTrimingEachRecord)
				{
					field = field.Trim();
				}
				csvFields.Add(field);
				m = m.NextMatch();
			}
			// 指定された型へ変換する 
			T _item = ConvertStructure(csvFields);
			csvRecords.Add(_item);
		}
		_sr.Close();
		csvRecords.TrimToSize();
		return csvRecords;
	}
	
	virtual public void WriteCSV(ArrayList csvFields)
	{
		char[] maches = {
			'"'
			, ','
			, '\r'
			, '\n'
		};
		//開く
		StreamWriter _sw = new StreamWriter(_csvPath, false,Encoding.GetEncoding(WriteEncoding));
		//レコードを書き込む
		foreach (T _item in csvFields)
		{
			bool isFirstLoop = true;
			//フィールドの取得
			foreach(string _field in ConvertStructure(_item))
			{
				//カンマを書き込む
				if (isFirstLoop)
				{
					isFirstLoop = false;
				}
				else
				{
					_sw.Write(',');
				}
				//"で囲む必要があるか調べる
				if (	(_field.IndexOfAny(maches) > -1)
					||	_field.StartsWith(" ")
					||	_field.StartsWith("\t")
					||	_field.EndsWith(" ")
					||	_field.EndsWith("\t")
					)
				{
					_sw.Write("\"");
					if (_field.IndexOf('"') > -1)
					{
						//"を""とする
						_sw.Write(_field.Replace("\"", "\"\""));
					}
					else
					{
						//フィールドを書き込む
						_sw.Write(_field);
					}
					_sw.Write("\"");
				}
				else
				{
					//フィールドを書き込む
					_sw.Write(_field);
				}
			}
			//改行する
			_sw.Write("\r\n");
		}
		//閉じる 
		_sw.Close();

	}

	/// <summary>
	/// 指定された文字列内にある文字列が幾つあるか数える
	/// </summary>
	/// <param name="strInput">strFindが幾つあるか数える文字列の参照</param>
	/// <param name="strFind">数える文字列</param>
	/// <returns>strInput内にstrFindが幾つあったか</returns>
	private int CountString(ref string strInput, string strFind)
	{
		int foundCount = 0;
		int sPos = strInput.IndexOf(strFind);
		while (sPos > -1)
		{
			foundCount++;
			sPos = strInput.IndexOf(strFind, sPos + 1);
		}
		return foundCount;
	}
}


具体化して使う場合は、以下のように実装。

class TestStructure
{
	public int Id;
	public string Name;
}

class TestStructureCSV : CSVFile<TestStructure>
{
	public TestStructureCSV(string csvfile)
		:base(csvfile)
	{
	}
	 
	/// <summary>
	/// 指定された型からArrayList型へ変換。
	/// </summary>
	/// <param name="item">指定された型</param>
	/// <return>ArrayList型(string)</return>
	override protected ArrayList ConvertStructure(TestStructure item)
	{
		ArrayList _al = new ArrayList();
		_al.Add(item.Id.ToString());
		_al.Add(item.Name);
		return _al;
	}
	/// <summary>
	/// ArrayList型から指定された型へ変換。
	/// </summary>
	/// <param name="item">ArrayList型(string)</param>
	/// <return>指定された型</return>
	override protected TestStructure ConvertStructure(ArrayList item)
	{
		TestStructure _al = new TestStructure();
		_al.Id = int.Parse(item[0]);
		_al.Name = item[1];
		return _al;
	}
}

具体化したクラスを使う場合は、以下のようににする。(読み込みの場合のみ...)

int _id = 1;
TestStructureCSV _tscsv = new TestStructureCSV("c:\\test.csv");
foreach (TestStructure _item in _tscsv.ReadCSV())
{
	if(_item.Id == _id)
	{
		Text1.Text = _item.Name;
		break;
	}
}

11/5追記

読み込み時に文字化けが発生することがあったので修正。
修正箇所はStreamReaderのコンストラクタ。