Newer
Older
PrismSoftware / DataAnalysis / CsvFile.cs
@Toshiya Nakaguchi Toshiya Nakaguchi on 25 Dec 2019 2 KB 解析
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Diagnostics;
using Microsoft.VisualBasic.FileIO;

namespace DataAnalysis {

    class CsvFile {
        public string[] Headers { get; private set; }
        public List<string[]> Data { get; private set; }
        public int Cols { get { return Headers.Length; } }
        public int Rows { get { return Data.Count; } }
        public bool IsOpen { get { return Headers != null; } }
        public string ErrorMsg { get; private set; }
        Dictionary<string, int> _HeaderIndex;

        /// <summary>
        /// ファイルを開く
        /// </summary>
        /// <param name="filename">ファイル名</param>
        /// <param name="requiredFields">必須列名</param>
        public void Open(string filename, IEnumerable<string> requiredFields) {
            var contents = ReadContents(filename);
            Headers = contents.First();
            if (!requiredFields.All(s => Headers.Contains(s))) {
                Headers = null;
                Data = null;
                throw new Exception("CSVファイルに必要な列がありません");
            }
            Data = contents.Skip(1).ToList();

            // インデックス辞書作成
            _HeaderIndex = Headers.Select((s, idx) => new { str = s, idx = idx })
                .ToDictionary(s => s.str, s => s.idx);
        }

        /// <summary>
        /// ヘッダの列番号(インデックス)を返す
        /// </summary>
        /// <param name="header">列番号(0開始)</param>
        /// <returns></returns>
        public int HeaderIndex(string header) {
            return _HeaderIndex[header];
        }

        /// <summary>
        /// CSVファイルを読み込む
        /// </summary>
        /// <param name="path"></param>CSVファイル名
        /// <param name="separator"></param>デリミタ
        /// <param name="encoding"></param>エンコード
        /// <returns></returns>
        public static IEnumerable<string[]> ReadContents(
            string path, string separator = ",", Encoding encoding = null) {

            using (Stream stream =
                new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))

            using (TextFieldParser parser =
                new TextFieldParser(stream, encoding ?? Encoding.GetEncoding("Shift_JIS"), true, false)) {

                parser.TextFieldType = FieldType.Delimited;
                parser.Delimiters = new[] { separator };
                parser.HasFieldsEnclosedInQuotes = true;
                parser.TrimWhiteSpace = true;
                while (parser.EndOfData == false) {
                    string[] fields = parser.ReadFields();
                    yield return fields;
                }
            }
        }
    }
}