/// <summary>
        /// Create a fixed-length data file using the provided data table
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="options"></param>
        /// <param name="filename"></param>
        public void Write(DataTable dt, FixedLengthImportOptions options, string filename)
        {
            #region Sanity Checks
            if (dt == null)
            {
                throw new ArgumentNullException("dt");
            }
            if (string.IsNullOrEmpty(filename))
            {
                throw new ArgumentNullException("filename");
            }
            #endregion

            //ResizeTableMaxLength(dt);

            var buffer = new byte[options.RecordLength];

            using (var fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.Read))
                using (var w = new BinaryWriter(fs))
                {
                    foreach (DataRow dr in dt.Rows)
                    {
                        #region initialize the buffer with spaces
                        for (int i = 0; i < buffer.Length; i++)
                        {
                            buffer[i] = 32;
                        }
                        #endregion

                        foreach (DataColumn dc in dt.Columns)
                        {
                            int start = options.Definition[dc.ColumnName].Start - 1;
                            int len   = options.Definition[dc.ColumnName].Length;
                            var value = Encoding.ASCII.GetBytes((dr[dc] ?? string.Empty).ToString());

                            Array.Copy(value, 0, buffer, start, len);
                        }

                        w.Write(buffer);

                        if (!string.IsNullOrEmpty(options.NewlineChar))
                        {
                            w.Write(options.NewlineChar);                       // ends the row with the specified newline delimiter
                        }
                    }

                    w.Flush();
                    w.Close();
                }
        }
        /// <summary>
        /// Read the filename and return a DataTable
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        public DataTable Read(string filename, FixedLengthImportOptions options)
        {
            #region Sanity Checks
            if (!File.Exists(filename))
            {
                throw new FileNotFoundException("File not found: " + filename);
            }

            if (options == null)
            {
                throw new ArgumentNullException("options");
            }
            if (options.Definition == null)
            {
                throw new ArgumentNullException("options.Definition");
            }
            if (options.Definition.Count == 0)
            {
                throw new ArgumentException("The list of field spec is empty");
            }
            if (options.Definition.RecordLength <= 0)
            {
                throw new ArgumentException("The record length must be greater than zero");
            }
            #endregion

            var def    = options.Definition;
            int reclen = def.RecordLength;
            var fi     = new FileInfo(filename);

            // make sure that file size is evenly divisible by the record length.
            // If not, we will assume that the definition is not valid for this file.
            if (fi.Length % reclen != 0)
            {
                throw new ArgumentException("File size does not break evenly by record length of " + reclen);
            }

            var dt = new DataTable();
            dt.TableName = Path.GetFileNameWithoutExtension(filename);

            #region Generate Data Columns
            foreach (var item in def)
            {
                DataColumn dc = new DataColumn(item.Name);
                dc.DataType = item.Type;
                if (item.Type == typeof(string))
                {
                    dc.MaxLength = item.Length;
                }
                dt.Columns.Add(dc);
            }

            #endregion

            #region Populate Data Rows
            int rownum = 0;
            foreach (var buffer in FileUtil.ReadFile(filename, reclen, 0))
            {
                if (buffer.Length == 0)
                {
                    continue;
                }

                rownum++;

                var dr = dt.NewRow();

                #region Convert data to column
                foreach (var item in def)
                {
                    string val;

#if SUPPORT_ENHANCE_FEATURES
                    if (item.Compute)
                    {
                        switch (item.Value.ToString().ToUpper())
                        {
                        case "COUNTER":
                            val = rownum.ToString();
                            break;

                        case "DATE":
                            val = DateTime.Now.ToShortDateString();
                            break;

                        case "TIME":
                            val = DateTime.Now.ToShortTimeString();
                            break;

                        case "DATETIME":
                            val = DateTime.Now.ToString("s");
                            break;

                        default:
                            throw new ArgumentException("unknown auto-compute key value = " + item.Value);
                        }
                    }
                    else
                    {
                        if (item.Start == -1)
                        {
                            val = StringUtil.Unescape(item.Value.ToString());
                        }
                        else
#else
                    {
#endif
                        { val = ASCIIEncoding.ASCII.GetString(buffer, item.Start - 1, item.Length).Trim(); }
                    }

                    if (string.IsNullOrEmpty(val))
                    {
                        continue;
                    }

                    object value = DataConvert.ChangeType(val, null, item.Type);
                    if (value == null)
                    {
                        throw new ArgumentException(string.Format("Converting '{0}' to {1} failed: ", val, item.Type.FullName));
                    }

                    dr[item.Name] = value;
                }
                #endregion

                dt.Rows.Add(dr);
            }
            #endregion

            return(dt);
        }