private void CheckKeyValueValidation()
        {
            if (Kind == EKind.ListRecord)
            {
                for (int i = 0; i < Records.Count; i++)
                {
                    if (Records[i].KeyValue != i)
                    {
                        throw new Exception(string.Format("Value in {0} column is not sequential like 0,1,2,3... in the file {1}", HeaderIndexLiteral, CsvFileName));
                    }
                }
            }
            else if (Kind == EKind.DicRecord)
            {
                for (int i = 0; i < Records.Count; i++)
                {
                    if (!CsvHelper.IsValidVariableName(Records[i].KeyName))
                    {
                        throw new Exception(string.Format("Key Name value {0} is not valid name at file {1}", Records[i].KeyName, CsvFileName));
                    }

                    if (!IsValidKeyValueForDicRecord(Records[i].KeyValue))
                    {
                        throw new Exception(string.Format("Key ID value {0} is not valid name at file {1}", Records[i].KeyValue, CsvFileName));
                    }
                    for (int j = i + 1; j < Records.Count; j++)
                    {
                        if (Records[i].KeyName == Records[j].KeyName)
                        {
                            throw new Exception(string.Format("Contains same name {0} in {1} column in the file {2}", Records[j].KeyName, HeaderIdNameLiteral, CsvFileName));
                        }

                        if (Records[i].KeyValue == Records[j].KeyValue)
                        {
                            throw new Exception(string.Format("Contains same value {0} in {1} column in the file {2}", Records[j].KeyValue, HeaderValueLiteral, CsvFileName));
                        }
                    }
                }
            }
            else
            {
                throw new Exception("Unknow csv file type");
            }
        }
        private void ReadHeader()
        {
            string[] headerInfo = mReader.ReadLine(0);

            if (headerInfo.Length < 1)
            {
                throw new CSVFileException(CsvFileName, "The header can not be empty");
            }

            // read header
            Header.Clear();
            mWidth = headerInfo.Length;
            for (int i = 0; i < mWidth; i++)
            {
                string[] tuple = headerInfo[i].Split(new char[] { ':' });
                if (tuple.Length == 1 && IsReservedColumnName(tuple[0]))
                {
                    if (tuple[0] == HeaderIdNameLiteral)
                    {
                        Header.Add(new HeaderRecord(tuple[0], "id", HeaderIdNameType, i));
                    }
                    else if (tuple[0] == HeaderValueLiteral)
                    {
                        Header.Add(new HeaderRecord(tuple[0], "dicval", HeaderValueType, i));
                    }
                    else if (tuple[0] == HeaderIndexLiteral)
                    {
                        Header.Add(new HeaderRecord(tuple[0], "int", HeaderIndexType, i));
                    }
                    else
                    {
                        throw new CSVFileException(CsvFileName, i + 1, 1, "Header name " + headerInfo[i] + " is not a valid name");
                    }
                }
                else if (tuple.Length != 2)
                {
                    throw new CSVFileException(CsvFileName, i + 1, 1, "Header name " + headerInfo[i] + " is not a valid name");
                }
                else
                {
                    if (CsvHelper.IsValidVariableName(tuple[0]))
                    {
                        Type type = CsvHelper.GetCsvColumnTypeByName(tuple[1]);
                        if (type == null)
                        {
                            throw new CSVFileException(CsvFileName, i + 1, 1, "Can not recognize name of type " + tuple[1]);
                        }
                        if (tuple[0][0] == '#')
                        {
                            CommentColumn.Add(i);
                        }
                        else
                        {
                            Header.Add(new HeaderRecord(tuple[0], tuple[1], type, i));
                        }
                    }
                    else
                    {
                        throw new CSVFileException(CsvFileName, i + 1, 1, tuple[0] + " is not a valid column name. A valid column name for header must the uppercase and lowercase letters A through Z, the underscore _ and, except for the first character, the digits 0 through 9.");
                    }
                }
            }

            int duplicatedColumn = CheckDuplicatedColumnName();

            if (duplicatedColumn > -1)
            {
                throw new CSVFileException(CsvFileName, duplicatedColumn + 1, 1, "Duplicated column name " + headerInfo[duplicatedColumn]);
            }

            int idPos    = Header.FindIndex((x) => { return(x.Name == HeaderIdNameLiteral); });
            int valuePos = Header.FindIndex((x) => { return(x.Name == HeaderValueLiteral); });
            int indexPos = Header.FindIndex((x) => { return(x.Name == HeaderIndexLiteral); });

            if (idPos > -1 && valuePos > -1 && indexPos > -1)
            {
                string error = string.Format("Confuse csv format, the List csv file need include {0} field in header, key-value csv file need include {1} {2} in header", HeaderIndexLiteral, HeaderValueLiteral, HeaderIdNameLiteral);
                throw new CSVFileException(CsvFileName, error);
            }
            else if (idPos > -1 && valuePos == -1 && indexPos == -1) //dictionary without value
            {
                Header.Add(new HeaderRecord(HeaderValueLiteral, "dicval", HeaderValueType, Header.Count));
                Kind            = EKind.DicRecord;
                dicWithoutValue = true;
            }
            else if (indexPos > -1 && idPos == -1 && valuePos == -1) // list csv
            {
                if (GetHeaderRecord(indexPos).Type == HeaderIndexType)
                {
                    Kind = EKind.ListRecord;
                }
                else
                {
                    string error = string.Format("List csv field {0} must with {1} type.", HeaderIndexLiteral, "int");
                    throw new CSVFileException(CsvFileName, error);
                }
            }
            else if (indexPos == -1 && idPos > -1 && valuePos > -1) // dictionary csv
            // check id type
            {
                if (GetHeaderRecord(idPos).Type != CsvHelper.GetCsvColumnTypeByName("id"))
                {
                    string error = string.Format("Header named {0} type does not match type {1} at file {2}", HeaderIdNameLiteral, CsvHelper.GetCsvColumnTypeByName("id"), CsvFileName);
                    throw new Exception(error);
                }

                // if contains _VALUE field, check the type is int
                if (GetHeaderRecord(valuePos).Type != HeaderValueType)
                {
                    string error = string.Format("Header named {0} type does not match type {1} at file {2}", HeaderValueLiteral, HeaderValueType, CsvFileName);
                    throw new Exception(error);
                }

                Kind = EKind.DicRecord;
            }
            else
            {
                string error = string.Format("Header is not valid, make sure you add {0}:int field for list csv file and {1}:int {2}:id fields for key-value csv file at first row", HeaderIndexLiteral, HeaderValueLiteral, HeaderIdNameLiteral);
                throw new CSVFileException(CsvFileName, error);
            }

            mHeight = mReader.Height;
        }