2014年4月24日木曜日

[C#]CSVファイルからDataTable生成

CSVファイルを読み込んで、DataTalbe に値を詰め込んで行く方法を検討してみました。
型変換を TypeConverter で行うと switch 文とかで分岐させることなくスッキリ書く事ができそうです。いちお、マージする機能もつけておきます。

        /// <summary>
        /// CSVデータからデータテーブル入力
        /// </summary>
        /// <remarks>
        /// table にはすでにカラムが生成されていること
        /// </remarks>
        /// <param name="table">OUT データテーブル</param>
        /// <param name="filePath">CSVファイルパス</param>
        /// <param name="isMerge">マージ有無</param>
        public void CsvToDataTable(DataTable table, string filePath, bool isMerge)
        {
            // 型コンバータ生成
            var convList = new List<TypeConverter>();
            foreach (DataColumn column in table.Columns)
            {
                convList.Add(TypeDescriptor.GetConverter(column.DataType));
            }

            // マージ判定
            DataTable importTable;
            if (isMerge)
            {
                importTable = table.Clone();
            }
            else
            {
                // マージしない場合は全件削除
                foreach (DataRow row in table.Rows)
                {
                    row.Delete();
                }
                importTable = table;
            }

            var count = importTable.Columns.Count;
            using (var reader = new StreamReader(filePath, Encoding.UTF8))
            {
                string line;
                var rowCount = 0;
                while ((line = reader.ReadLine()) != null)
                {
                    rowCount++;
                    var csvData = line.Split(',');
                    var row = importTable.NewRow();

                    for (int cellCount = 0; cellCount < count; cellCount++)
                    {
                        try
                        {
                            // 型別に変換
                            var type = importTable.Columns[cellCount].DataType;
                            if (type == typeof(byte[]))
                            {
                                row[cellCount] = HexStringToByteArray(csvData[cellCount]);
                            }
                            else if (type == typeof(string) || type == typeof(DateTime))
                            {
                                if (csvData[cellCount] != null)
                                {
                                    row[cellCount] = convList[cellCount].ConvertFrom(csvData[cellCount]);
                                }
                                else
                                {
                                    row.SetField(cellCount, DBNull.Value);
                                }
                            }
                            else
                            {
                                if (!string.IsNullOrEmpty(csvData[cellCount]))
                                {
                                    row[cellCount] = convList[cellCount].ConvertFrom(csvData[cellCount]);
                                }
                                else
                                {
                                    row.SetField(cellCount, DBNull.Value);
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            throw new Exception(string.Format("[行:{0} 列 {1}]{2}", rowCount, cellCount, e.Message));
                        }
                    }
                    importTable.Rows.Add(row);
                }

            }
            if (isMerge)
            {
                table.Merge(importTable);
            }
        }

        /// <summary>
        /// 16進数文字列バイト配列変換
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public byte[] HexStringToByteArray(string data)
        {
            if (data == null)
                throw new ArgumentNullException();
            if (data.Length % 2 == 1)
                data = "0" + data;  // 補正

            var list = new List<byte>();
            for (int i = 0; i < data.Length - 1; i++, i++)
                list.Add(Convert.ToByte(data.Substring(i, 2), 16));
            return list.ToArray();
        }


関連






0 件のコメント:

コメントを投稿