/// <summary>
            /// ファイルインデックスのコンストラクタ
            /// </summary>
            /// <param name="index">インデックス番号</param>
            /// <param name="fileName">ファイル名</param>
            /// <param name="rowData"></param>
            public FileIndex(int index, string fileName, KCVDBRow rowData)
            {
                this.IndexString = index.ToString();
                this.DateString  = (rowData.HttpDate.ToJst()).Date.ToShortDateString();
                this.SessionId   = rowData.SessionId;
                this.AgentId     = rowData.AgentId;

                this.FileName = fileName;
            }
        /// <summary>
        /// 7zipファイルを解凍しながら行単位でパースしつつ、解析イベントを挿入します
        /// </summary>
        /// <param name="archive">7zipの書庫ファイル</param>
        /// <param name="events">解析イベントの一覧</param>
        /// <param name="skip">冒頭のスキップするファイル数</param>
        /// <param name="take">取るファイル数</param>
        public static void AnalyzeAllSevenZipArchives(string archive, LogFileAnalyzeEvents events, int skip = 0, int take = -1)
        {
            var skipremain = skip;
            var takeremain = (take < 0) ? int.MaxValue : take;

            new LogDirectory(archive).Subscribe(
                logFile =>
            {
                if (skipremain > 0)
                {
                    skipremain--;
                    return;
                }
                if (takeremain <= 0)
                {
                    return;
                }
                takeremain--;

                if (events.OnFileLoaded != null)
                {
                    events.OnFileLoaded(logFile, new Event.LogFileEventArgs(logFile));
                }
                logFile.Subscribe(
                    line =>
                {
                    if (events.OnAnalyzing != null)
                    {
                        KCVDBRow row;
                        if (KCVDBRow.TryParse(line, out row))
                        {
                            events.OnAnalyzing(logFile, new Event.RowAnalyzingEventArgs(logFile, row));
                        }
                    }
                },
                    error =>
                {
                    if (events.OnError != null)
                    {
                        events.OnError(logFile, new Event.ExceptionEventArgs(error));
                    }
                },
                    () =>
                {
                    if (events.OnCompleted != null)
                    {
                        events.OnCompleted(logFile, new Event.LogFileEventArgs(logFile));
                    }
                });
            }
                );
        }
 /// <summary>
 /// ファイル形式ごとに必要に応じて解凍しながら読み込み、行単位でパースします
 /// </summary>
 /// <param name="filePath">ファイルのパス</param>
 /// <returns>行単位のパースされたアイテム</returns>
 public static IEnumerable <KCVDBRow> ParseAllLines(string filePath)
 {
     foreach (var l in ReadAllLines(filePath))
     {
         KCVDBRow row;
         if (!KCVDBRow.TryParse(l, out row))
         {
             yield break;
         }
         else
         {
             yield return(row);
         }
     }
 }
        /// <summary>
        /// ファイルインデックスをロード
        /// </summary>
        /// <param name="fileIndexPath"></param>
        /// <returns></returns>
        public static IList <FileIndex> FileIndexLoader(string fileIndexPath)
        {
            var list = new List <FileIndex>();

            foreach (var l in File.ReadAllLines(fileIndexPath))
            {
                KCVDBRow row;
                if (KCVDBRow.TryParse(l, out row))
                {
                    FileIndex index;
                    if (FileIndex.TryParse(l, out index))
                    {
                        list.Add(index);
                    }
                }
            }
            return(list);
        }
        /// <summary>
        /// KCVDBのログの行単位の文字列のパースを試みます。戻り値は変換に成功したかどうかを示します
        /// </summary>
        /// <param name="lineStr">KCVDBの行単位の文字列</param>
        /// <param name="kcvdbRow">変換に成功した場合は対応するKCVDBRow、失敗した場合はnew KCVDBRow()が格納されます</param>
        /// <returns></returns>
        public static bool TryParse(string lineStr, out KCVDBRow kcvdbRow)
        {
            if (lineStr == null)
            {
                kcvdbRow = new KCVDBRow();
                return(false);
            }

            var cell = lineStr.Split('\t');

            // [0] AgentID
            // [1] SessionID
            // [2] Path
            // [3] HttpStatusCode
            // [4] ServerTime
            // [5] LocalTime
            // [6] RequestBody
            // [7] ResponseBody

            if (cell.Length != 8)
            {
                kcvdbRow = new KCVDBRow();
                return(false);
            }

            kcvdbRow                  = new KCVDBRow();
            kcvdbRow.AgentId          = cell[0];
            kcvdbRow.SessionId        = cell[1];
            kcvdbRow.RequestUri       = cell[2];
            kcvdbRow.StatusCodeString = cell[3];
            kcvdbRow.HttpDateString   = cell[4];
            kcvdbRow.LocalTimeString  = cell[5];
            kcvdbRow.RequestValue     = cell[6];
            kcvdbRow.ResponseValue    = cell[7];

            return(true);
        }