Represents a descriprion of dBase field.
        ///// <summary>
        ///// Получает или устанавливает кодировку используемую для интерпретации записей dbf-файла
        ///// </summary>
        ///// <remarks>
        ///// если не задана, будет предпринята попытка определить корректную кодировку по языковому драйверу
        ///// </remarks>
        //public Encoding Encoding
        //{
        //    get { return _encoding; }
        //    set { _encoding = value; }
        //}

        /// <summary>
        /// Gets a dBase row.
        /// </summary>
        /// <param name="oid">A row id value</param>
        /// <param name="table">A System.Data.DataTable instance containing dBase data</param>
        /// <returns>A data row</returns>
        internal DataRow GetRow(uint oid, DataTable table)
        {
            if (!_isOpen)
            {
                throw new ApplicationException("Unable to read the closed dbf-file");
            }
            if (oid >= _dbaseHeader.NumRecords)
            {
                throw new ArgumentOutOfRangeException("Incorrect record identity", "oid");
            }
            _fs.Seek(_dbaseHeader.HeaderLength + oid * _dbaseHeader.RecordLength, 0);

            DataRow dr = table.NewRow();

            if (_br.ReadChar() == '*') //is record marked as deleted?
            {
                return(null);
            }

            for (int i = 0; i < _dbaseHeader.DBaseColumns.Length; i++)
            {
                DbaseFieldDescriptor dbf = _dbaseHeader.DBaseColumns[i];
                dr[dbf.Name] = readDbfValue(dbf);
            }
            return(dr);
        }
        /// <summary>
        /// Converts a CLR type to corresponding dBase type.
        /// </summary>
        /// <param name="type">A CLR type</param>
        /// <returns>A corresponding dBase type</returns>
		public static char GetDbaseType(Type type)
		{
			DbaseFieldDescriptor dbaseColumn = new DbaseFieldDescriptor();
            if (type == typeof(Char))
                return 'C';
            if (type == typeof(string))
                return 'C';
            else if (type == typeof(Double))
                return 'N';
            else if (type == typeof(Single))
                return 'N';
            else if (type == typeof(Int16))
                return 'N';
            else if (type == typeof(Int32))
                return 'N';
            else if (type == typeof(Int64))
                return 'N';
            else if (type == typeof(UInt16))
                return 'N';
            else if (type == typeof(UInt32))
                return 'N';
            else if (type == typeof(UInt64))
                return 'N';
            else if (type == typeof(Decimal))
                return 'N';
            else if (type == typeof(Boolean))
                return 'L';
            else if (type == typeof(DateTime))
                return 'D';

			throw new NotSupportedException(String.Format("{0} does not have a corresponding dbase type.", type.Name));
		}
        /// <summary>
        /// Converts a CLR type to corresponding dBase type.
        /// </summary>
        /// <param name="type">A CLR type</param>
        /// <returns>A corresponding dBase type</returns>
        public static char GetDbaseType(Type type)
        {
            DbaseFieldDescriptor dbaseColumn = new DbaseFieldDescriptor();

            if (type == typeof(Char))
            {
                return('C');
            }
            if (type == typeof(string))
            {
                return('C');
            }
            else if (type == typeof(Double))
            {
                return('N');
            }
            else if (type == typeof(Single))
            {
                return('N');
            }
            else if (type == typeof(Int16))
            {
                return('N');
            }
            else if (type == typeof(Int32))
            {
                return('N');
            }
            else if (type == typeof(Int64))
            {
                return('N');
            }
            else if (type == typeof(UInt16))
            {
                return('N');
            }
            else if (type == typeof(UInt32))
            {
                return('N');
            }
            else if (type == typeof(UInt64))
            {
                return('N');
            }
            else if (type == typeof(Decimal))
            {
                return('N');
            }
            else if (type == typeof(Boolean))
            {
                return('L');
            }
            else if (type == typeof(DateTime))
            {
                return('D');
            }

            throw new NotSupportedException(String.Format("{0} does not have a corresponding dbase type.", type.Name));
        }
Beispiel #4
0
        /// <summary>
        /// Removes a column.
        /// </summary>
        /// <param name="fieldName">A filed name</param>
        /// <returns>An index of the removed filed, -1 if filed is not found</returns>
        public int RemoveColumn(string fieldName)
        {
            int retCol     = -1;
            int tempLength = 1;

            DbaseFieldDescriptor[] tempFieldDescriptors =
                new DbaseFieldDescriptor[_dbaseColumns.Length - 1];
            for (int i = 0, j = 0; i < _dbaseColumns.Length; i++)
            {
                if (fieldName.ToLower() != (_dbaseColumns[i].Name.Trim().ToLower()))
                {
                    // if this is the last field and we still haven't found the
                    // named field
                    if (i == j && i == _dbaseColumns.Length - 1)
                    {
                        return(retCol);
                    }
                    tempFieldDescriptors[j]             = _dbaseColumns[i];
                    tempFieldDescriptors[j].DataAddress = tempLength;
                    tempLength += tempFieldDescriptors[j].Length;
                    // only increment j on non-matching fields
                    j++;
                }
                else
                {
                    retCol = i;
                }
            }

            // set the new fields.
            _dbaseColumns = tempFieldDescriptors;
            _headerLength = 33 + 32 * _dbaseColumns.Length;
            _numFields    = _dbaseColumns.Length;
            _recordLength = tempLength;

            return(retCol);
        }
Beispiel #5
0
        private object readDbfValue(DbaseFieldDescriptor dbf)
        {
            byte[] bytes = _br.ReadBytes(dbf.Length);

            switch (dbf.DataType.ToString())
            {
                case "System.String":
                    //if (_encoding == null)
                    //    return _fileEncoding.GetString(bytes).Replace("\0", "").Trim();
                    //else
                        return _dbaseHeader.Encoding.GetString(bytes).Replace("\0", "").Trim();

                case "System.Double":
                    string temp = System.Text.Encoding.UTF7.GetString(bytes).Replace("\0", "").Trim();
                    double dbl = 0;
                    if (double.TryParse(temp, System.Globalization.NumberStyles.Float, _numberFormat, out dbl))
                        return dbl;
                    else
                        return DBNull.Value;

                case "System.Int16":
                    string temp16 = System.Text.Encoding.UTF7.GetString((bytes)).Replace("\0", "").Trim();
                    Int16 i16 = 0;
                    if (Int16.TryParse(temp16, System.Globalization.NumberStyles.Float, _numberFormat, out i16))
                        return i16;
                    else
                        return DBNull.Value;

                case "System.Int32":
                    string temp32 = System.Text.Encoding.UTF7.GetString((bytes)).Replace("\0", "").Trim();
                    Int32 i32 = 0;
                    if (Int32.TryParse(temp32, System.Globalization.NumberStyles.Float, _numberFormat, out i32))
                        return i32;
                    else
                        return DBNull.Value;

                case "System.Int64":
                    string temp64 = System.Text.Encoding.UTF7.GetString((bytes)).Replace("\0", "").Trim();
                    Int64 i64 = 0;
                    if (Int64.TryParse(temp64, System.Globalization.NumberStyles.Float, _numberFormat, out i64))
                        return i64;
                    else
                        return DBNull.Value;

                case "System.Single":
                    string temp4 = System.Text.Encoding.UTF8.GetString((bytes));
                    float f = 0;
                    if (float.TryParse(temp4, System.Globalization.NumberStyles.Float, _numberFormat, out f))
                        return f;
                    else
                        return DBNull.Value;

                case "System.Boolean":
                    char tempChar = Convert.ToChar(bytes[0]);// BitConverter.ToChar(bytes, 0);// _br.ReadChar();
                    return ((tempChar == 'T') || (tempChar == 't') || (tempChar == 'Y') || (tempChar == 'y'));

                case "System.DateTime":
#if !MONO
                    DateTime date;
                    if (DateTime.TryParseExact(System.Text.Encoding.UTF7.GetString((bytes)),
                        "yyyyMMdd", _numberFormat, System.Globalization.DateTimeStyles.None, out date))
                        return date;
                    else
                        return DBNull.Value;

#else // в mono еще не реализован метод DateTime.TryParseExact
					try 
					{
						return DateTime.ParseExact (System.Text.Encoding.UTF7.GetString((bytes)), 	
						"yyyyMMdd", _numberFormat, System.Globalization.DateTimeStyles.None );
					}
					catch 
					{
						return DBNull.Value;
					}

#endif
                default:
                    throw (new NotSupportedException("Unable to process field '" + dbf.Name + "' (data type '" + dbf.DataType.ToString() + "')"));
            }

        }
Beispiel #6
0
        /// <summary>
        /// Writes a row.
        /// </summary>
        /// <param name="columnValues">A list containing the column values</param>
        /// <param name="RecNum">A number of record</param>
        public void Write(IList columnValues, int RecNum)
        {
            if (columnValues == null)
            {
                throw new ArgumentNullException("columnValues");
            }
            if (!_headerWritten)
            {
                throw new InvalidOperationException("Header records need to be written first.");
            }
            int i = 0;

            _writer.BaseStream.Seek(this._header.HeaderLength + RecNum * this._header.RecordLength, SeekOrigin.Begin);

            _writer.Write((byte)0x20); // the deleted flag
            foreach (object columnValue in columnValues)
            {
                DbaseFieldDescriptor headerField = _header.DBaseColumns[i];

                if (columnValue == null)
                {
                    // Don't corrupt the file by not writing if the value is null.
                    // Instead, treat it like an empty string.
                    Write(string.Empty, headerField.Length);
                }
                else if (headerField.DataType == typeof(string))
                {
                    // If the column is a character column, the values in that
                    // column should be treated as text, even if the column value
                    // is not a string.
                    Write(columnValue.ToString(), headerField.Length);
                }
                else if (IsRealType(columnValue.GetType()))
                {
                    decimal decValue = Convert.ToDecimal(columnValue);
                    Write(decValue, headerField.Length, headerField.DecimalCount);
                }
                else if (IsIntegerType(columnValue.GetType()))
                {
                    Write(Convert.ToDecimal(columnValue), headerField.Length, headerField.DecimalCount);
                }
                else if (columnValue is Decimal)
                {
                    Write((decimal)columnValue, headerField.Length, headerField.DecimalCount);
                }
                else if (columnValue is Boolean)
                {
                    Write((bool)columnValue);
                }
                else if (columnValue is string)
                {
                    Write((string)columnValue, headerField.Length);
                }
                else if (columnValue is DateTime)
                {
                    Write((DateTime)columnValue);
                }
                else if (columnValue is Char)
                {
                    Write((Char)columnValue, headerField.Length);
                }

                i++;
            }
        }
Beispiel #7
0
        /// <summary>
        /// Generates a dBase file header.
        /// </summary>
        /// <param name="dbFields">An array containing the dBase filed descriptors</param>
        /// <param name="count">The record count</param>
        /// <returns>A stub of dBase file header</returns>
        public static DbaseFileHeader GetDbaseHeader(DbaseFieldDescriptor[] dbFields, int count)
        {
            DbaseFileHeader header = new DbaseFileHeader();
            header.NumRecords = count;

            foreach (DbaseFieldDescriptor dbField in dbFields)
                header.AddColumn(dbField.Name, dbField.DbaseType, dbField.DataType, dbField.Length, dbField.DecimalCount);

            return header;
        }
Beispiel #8
0
        /// <summary>
        /// Computes a maximum length of field taking into account all the values.
        /// </summary>
        /// <param name="field">A descriptor of field</param>
        /// <param name="columnValues">A field value enumerator</param>
        public void RecountColumnLength(DbaseFieldDescriptor field, IEnumerable columnValues)
        {
            int size = 0;
            int decimalCount = 0;

            System.Globalization.NumberFormatInfo numberFormatInfo = new System.Globalization.NumberFormatInfo();
            numberFormatInfo.NumberDecimalSeparator = ".";

            foreach (object value in columnValues)
            {
                if (field.DataType == typeof(string))
                {
                    string svalue = Convert.ToString(value);
                    int s = this.Encoding.GetBytes(svalue).Length;

                    if (s > size) size = s;
                }
                //else if (field.DataType == typeof(Int16) || field.DataType == typeof(Int32) || field.DataType == typeof(Int64)
                //         || field.DataType == typeof(UInt16) || field.DataType == typeof(UInt32) || field.DataType == typeof(UInt64))
                //{
                //    size = System.Runtime.InteropServices.Marshal.SizeOf(field.DataType);
                //    decimalCount = 0;
                //}
                else if (field.DataType == typeof(Double) ||field.DataType == typeof(Single) || field.DataType == typeof(Decimal) ||
                         field.DataType == typeof(Int16) || field.DataType == typeof(Int32) || field.DataType == typeof(Int64)
                         || field.DataType == typeof(UInt16) || field.DataType == typeof(UInt32) || field.DataType == typeof(UInt64))
                {
                    string svalue = Convert.ToString(value, numberFormatInfo);
                    if (svalue.Length > size) size = svalue.Length;
                    int decimalSepIndex = svalue.IndexOf(".");
                    if (decimalSepIndex != -1)
                    {
                        if (svalue.Length - decimalSepIndex - 1 > decimalCount)
                            decimalCount = Math.Max(decimalCount, svalue.Length - decimalSepIndex - 1);
                    }
                    //else if (decimalCount == 0)
                    //{
                    //    size += 3; // с учетом разделителя
                    //    decimalCount = 2;
                    //}
                }
            }

            if (field.DataType == typeof(Double) || field.DataType == typeof(Single) || field.DataType == typeof(Decimal))
            {
                if (decimalCount == 0)
                {
                    size += 3; // с учетом разделителя
                    decimalCount = 2;
                }
            }

            if (size != 0)
            {
                this._recordLength = this._recordLength - field.Length + size;
                field.Length = size;
                if (decimalCount != 0) field.DecimalCount = decimalCount;
            }
        }
Beispiel #9
0
        /// <summary>
        /// Reads a dBase header.
        /// </summary>
        /// <param name="reader">A System.IO.BinaryReader instance to read header</param>
        public void Read(BinaryReader reader)
        {
            // type of reader.
            _fileType = reader.ReadByte();
            if (_fileType != 0x03)
                throw new NotSupportedException("Unsupported DBF Type " + _fileType);

            // parse the update date information.
            int year = (int)reader.ReadByte();
            int month = (int)reader.ReadByte();
            int day = (int)reader.ReadByte();
            _updateDate = new DateTime(year + 1900, month, day);

            // read the number of records.
            _numRecords = reader.ReadInt32();

            // read the length of the header structure.
            _headerLength = reader.ReadInt16();

            // read the length of a record
            _recordLength = reader.ReadInt16();

            // skip the reserved bytes in the header.
            //in.skipBytes(20);
            //reader.ReadBytes(20);
            reader.BaseStream.Seek(29, SeekOrigin.Begin);

            //языковой драйвер
            _encoding = getDbaseLanguageDriver(reader.ReadByte());           
            
            reader.BaseStream.Seek(32, SeekOrigin.Begin);

            // calculate the number of Fields in the header
            _numFields = (_headerLength - _fileDescriptorSize - 1) / _fileDescriptorSize;

            // read all of the header records
            _dbaseColumns = new DbaseFieldDescriptor[_numFields];

            for (int i = 0; i < _numFields; i++)
            {
                _dbaseColumns[i] = new DbaseFieldDescriptor();

                // read the field name				
                byte[] buffer = reader.ReadBytes(11);
                string name = _encoding.GetString(buffer);

                if (name.Contains("\0"))
                    name = name.Substring(0, name.IndexOf('\0'));

                name = name.Replace("\0", "").Trim();

                int nullPoint = name.IndexOf((char)0);
                if (nullPoint != -1)
                    name = name.Substring(0, nullPoint);
                _dbaseColumns[i].Name = name;

                // read the field type
                _dbaseColumns[i].DbaseType = (char)reader.ReadByte();
                _dbaseColumns[i].DataType = DbaseFieldDescriptor.GetDataType(_dbaseColumns[i].DbaseType);

                // read the field data address, offset from the start of the record.
                _dbaseColumns[i].DataAddress = reader.ReadInt32();

                // read the field length in bytes
                int tempLength = (int)reader.ReadByte();
                if (tempLength < 0) tempLength = tempLength + 256;
                _dbaseColumns[i].Length = tempLength;

                // read the field decimal count in bytes
                _dbaseColumns[i].DecimalCount = (int)reader.ReadByte();
                if (_dbaseColumns[i].DecimalCount == 0 && _dbaseColumns[i].DataType == typeof(double))
                    if (_dbaseColumns[i].Length <= 2)
                        _dbaseColumns[i].DataType = typeof(Int16);
                    else if (_dbaseColumns[i].Length <= 4)
                        _dbaseColumns[i].DataType = typeof(Int32);
                    else
                        _dbaseColumns[i].DataType = typeof(Int64);

                // read the reserved bytes.
                //reader.skipBytes(14);
                reader.ReadBytes(14);
            }

            // Last byte is a marker for the end of the field definitions.
            reader.ReadBytes(1);
        }       
Beispiel #10
0
        /// <summary>
        /// Removes a column.
        /// </summary>
        /// <param name="fieldName">A filed name</param>
        /// <returns>An index of the removed filed, -1 if filed is not found</returns>
        public int RemoveColumn(string fieldName)
        {
            int retCol = -1;
            int tempLength = 1;
            DbaseFieldDescriptor[] tempFieldDescriptors =
                new DbaseFieldDescriptor[_dbaseColumns.Length - 1];
            for (int i = 0, j = 0; i < _dbaseColumns.Length; i++)
            {
                if (fieldName.ToLower() != (_dbaseColumns[i].Name.Trim().ToLower()))
                {
                    // if this is the last field and we still haven't found the
                    // named field
                    if (i == j && i == _dbaseColumns.Length - 1)
                        return retCol;
                    tempFieldDescriptors[j] = _dbaseColumns[i];
                    tempFieldDescriptors[j].DataAddress = tempLength;
                    tempLength += tempFieldDescriptors[j].Length;
                    // only increment j on non-matching fields
                    j++;
                }
                else retCol = i;
            }

            // set the new fields.
            _dbaseColumns = tempFieldDescriptors;
            _headerLength = 33 + 32 * _dbaseColumns.Length;
            _numFields = _dbaseColumns.Length;
            _recordLength = tempLength;

            return retCol;
        }
Beispiel #11
0
        /// <summary>
        /// Adds a column.
        ///</summary>
        /// <param name="fieldName">A filed name</param>
        /// <param name="fieldType">A character defining a dBAse filed type (C N L or D)</param>
        /// <param name="fieldLength">A length of field in bytes</param>
        /// <param name="decimalCount">A number of decimal characters</param>
        /// <param name="DataType">A CLR data type</param>
        public void AddColumn(string fieldName, char fieldType, Type DataType, int fieldLength, int decimalCount)
        {
            if (fieldLength <= 0) fieldLength = 1;
            if (_dbaseColumns == null) _dbaseColumns = new DbaseFieldDescriptor[0];
            int tempLength = 1;  // the length is used for the offset, and there is a * for deleted as the first byte
            DbaseFieldDescriptor[] tempFieldDescriptors = new DbaseFieldDescriptor[_dbaseColumns.Length + 1];
            for (int i = 0; i < _dbaseColumns.Length; i++)
            {
                _dbaseColumns[i].DataAddress = tempLength;
                tempLength = tempLength + _dbaseColumns[i].Length;
                tempFieldDescriptors[i] = _dbaseColumns[i];
            }
            tempFieldDescriptors[_dbaseColumns.Length] = new DbaseFieldDescriptor();
            tempFieldDescriptors[_dbaseColumns.Length].Length = fieldLength;
            tempFieldDescriptors[_dbaseColumns.Length].DecimalCount = decimalCount;
            tempFieldDescriptors[_dbaseColumns.Length].DataAddress = tempLength;

            // set the field name
            string tempFieldName = fieldName;
            if (tempFieldName == null) tempFieldName = "NoName";
            if (tempFieldName.Length > 11)
            {
                tempFieldName = tempFieldName.Substring(0, 11);
                //!!!Trace.Write("FieldName " + fieldName + " is longer than 11 characters, truncating to " + tempFieldName);
            }
            tempFieldDescriptors[_dbaseColumns.Length].Name = tempFieldName;

            // the field type
            tempFieldDescriptors[_dbaseColumns.Length].DataType = DataType;
            if ((fieldType == 'C') || (fieldType == 'c'))
            {
                tempFieldDescriptors[_dbaseColumns.Length].DbaseType = 'C';
            }
            else if ((fieldType == 'S') || (fieldType == 's'))
            {
                tempFieldDescriptors[_dbaseColumns.Length].DbaseType = 'C';
                tempFieldDescriptors[_dbaseColumns.Length].Length = 8;
            }
            else if ((fieldType == 'D') || (fieldType == 'd'))
            {
                tempFieldDescriptors[_dbaseColumns.Length].DbaseType = 'D';
                tempFieldDescriptors[_dbaseColumns.Length].Length = 8;
            }
            else if ((fieldType == 'F') || (fieldType == 'f'))
            {
                tempFieldDescriptors[_dbaseColumns.Length].DbaseType = 'F';
            }
            else if ((fieldType == 'N') || (fieldType == 'n'))
            {
                tempFieldDescriptors[_dbaseColumns.Length].DbaseType = 'N';
                if (decimalCount < 0)
                {
                    tempFieldDescriptors[_dbaseColumns.Length].DecimalCount = 0;
                }
                if (decimalCount > fieldLength - 1)
                {
                    tempFieldDescriptors[_dbaseColumns.Length].DecimalCount = fieldLength - 1;
                }
            }
            else if ((fieldType == 'L') || (fieldType == 'l'))
            {
                tempFieldDescriptors[_dbaseColumns.Length].DbaseType = 'L';
                tempFieldDescriptors[_dbaseColumns.Length].Length = 1;
            }
            else
            {
                throw new NotSupportedException("Unsupported field type " + fieldType + " For column " + fieldName);
            }
            // the length of a record
            tempLength = tempLength + tempFieldDescriptors[_dbaseColumns.Length].Length;

            // set the new fields.
            _dbaseColumns = tempFieldDescriptors;
            _headerLength = 33 + 32 * _dbaseColumns.Length;
            _numFields = _dbaseColumns.Length;
            _recordLength = tempLength;
        }
Beispiel #12
0
        /// <summary>
        /// Computes a maximum length of field taking into account all the values.
        /// </summary>
        /// <param name="field">A descriptor of field</param>
        /// <param name="columnValues">A field value enumerator</param>
        public void RecountColumnLength(DbaseFieldDescriptor field, IEnumerable columnValues)
        {
            int size         = 0;
            int decimalCount = 0;

            System.Globalization.NumberFormatInfo numberFormatInfo = new System.Globalization.NumberFormatInfo();
            numberFormatInfo.NumberDecimalSeparator = ".";

            foreach (object value in columnValues)
            {
                if (field.DataType == typeof(string))
                {
                    string svalue = Convert.ToString(value);
                    int    s      = this.Encoding.GetBytes(svalue).Length;

                    if (s > size)
                    {
                        size = s;
                    }
                }
                //else if (field.DataType == typeof(Int16) || field.DataType == typeof(Int32) || field.DataType == typeof(Int64)
                //         || field.DataType == typeof(UInt16) || field.DataType == typeof(UInt32) || field.DataType == typeof(UInt64))
                //{
                //    size = System.Runtime.InteropServices.Marshal.SizeOf(field.DataType);
                //    decimalCount = 0;
                //}
                else if (field.DataType == typeof(Double) || field.DataType == typeof(Single) || field.DataType == typeof(Decimal) ||
                         field.DataType == typeof(Int16) || field.DataType == typeof(Int32) || field.DataType == typeof(Int64) ||
                         field.DataType == typeof(UInt16) || field.DataType == typeof(UInt32) || field.DataType == typeof(UInt64))
                {
                    string svalue = Convert.ToString(value, numberFormatInfo);
                    if (svalue.Length > size)
                    {
                        size = svalue.Length;
                    }
                    int decimalSepIndex = svalue.IndexOf(".");
                    if (decimalSepIndex != -1)
                    {
                        if (svalue.Length - decimalSepIndex - 1 > decimalCount)
                        {
                            decimalCount = Math.Max(decimalCount, svalue.Length - decimalSepIndex - 1);
                        }
                    }
                    //else if (decimalCount == 0)
                    //{
                    //    size += 3; // с учетом разделителя
                    //    decimalCount = 2;
                    //}
                }
            }

            if (field.DataType == typeof(Double) || field.DataType == typeof(Single) || field.DataType == typeof(Decimal))
            {
                if (decimalCount == 0)
                {
                    size        += 3; // с учетом разделителя
                    decimalCount = 2;
                }
            }

            if (size != 0)
            {
                this._recordLength = this._recordLength - field.Length + size;
                field.Length       = size;
                if (decimalCount != 0)
                {
                    field.DecimalCount = decimalCount;
                }
            }
        }
Beispiel #13
0
        /// <summary>
        /// Reads a dBase header.
        /// </summary>
        /// <param name="reader">A System.IO.BinaryReader instance to read header</param>
        public void Read(BinaryReader reader)
        {
            // type of reader.
            _fileType = reader.ReadByte();
            if (_fileType != 0x03)
            {
                throw new NotSupportedException("Unsupported DBF Type " + _fileType);
            }

            // parse the update date information.
            int year        = (int)reader.ReadByte();
            int month       = (int)reader.ReadByte();
            int day         = (int)reader.ReadByte();
            int yearShifted = year + 1900;

            try
            {
                _updateDate = new DateTime(yearShifted, month, day);
            }
            catch (ArgumentOutOfRangeException ex)
            {
                Debug.WriteLine("Data reading failed.");
                _updateDate = DateTime.MinValue;
            }

            // read the number of records.
            _numRecords = reader.ReadInt32();

            // read the length of the header structure.
            _headerLength = reader.ReadInt16();

            // read the length of a record
            _recordLength = reader.ReadInt16();

            // skip the reserved bytes in the header.
            //in.skipBytes(20);
            //reader.ReadBytes(20);
            reader.BaseStream.Seek(29, SeekOrigin.Begin);

            //языковой драйвер
            _encoding = getDbaseLanguageDriver(reader.ReadByte());

            reader.BaseStream.Seek(32, SeekOrigin.Begin);

            // calculate the number of Fields in the header
            _numFields = (_headerLength - _fileDescriptorSize - 1) / _fileDescriptorSize;

            // read all of the header records
            _dbaseColumns = new DbaseFieldDescriptor[_numFields];

            for (int i = 0; i < _numFields; i++)
            {
                _dbaseColumns[i] = new DbaseFieldDescriptor();

                // read the field name
                byte[] buffer = reader.ReadBytes(11);
                string name   = _encoding.GetString(buffer);

                if (name.Contains("\0"))
                {
                    name = name.Substring(0, name.IndexOf('\0'));
                }

                name = name.Replace("\0", "").Trim();

                int nullPoint = name.IndexOf((char)0);
                if (nullPoint != -1)
                {
                    name = name.Substring(0, nullPoint);
                }
                _dbaseColumns[i].Name = name;

                // read the field type
                _dbaseColumns[i].DbaseType = (char)reader.ReadByte();
                _dbaseColumns[i].DataType  = DbaseFieldDescriptor.GetDataType(_dbaseColumns[i].DbaseType);

                // read the field data address, offset from the start of the record.
                _dbaseColumns[i].DataAddress = reader.ReadInt32();

                // read the field length in bytes
                int tempLength = (int)reader.ReadByte();
                if (tempLength < 0)
                {
                    tempLength = tempLength + 256;
                }
                _dbaseColumns[i].Length = tempLength;

                // read the field decimal count in bytes
                _dbaseColumns[i].DecimalCount = (int)reader.ReadByte();
                if (_dbaseColumns[i].DecimalCount == 0 && _dbaseColumns[i].DataType == typeof(double))
                {
                    if (_dbaseColumns[i].Length <= 2)
                    {
                        _dbaseColumns[i].DataType = typeof(Int16);
                    }
                    else if (_dbaseColumns[i].Length <= 4)
                    {
                        _dbaseColumns[i].DataType = typeof(Int32);
                    }
                    else
                    {
                        _dbaseColumns[i].DataType = typeof(Int64);
                    }
                }

                // read the reserved bytes.
                //reader.skipBytes(14);
                reader.ReadBytes(14);
            }

            // Last byte is a marker for the end of the field definitions.
            reader.ReadBytes(1);
        }
Beispiel #14
0
        /// <summary>
        /// Adds a column.
        ///</summary>
        /// <param name="fieldName">A filed name</param>
        /// <param name="fieldType">A character defining a dBAse filed type (C N L or D)</param>
        /// <param name="fieldLength">A length of field in bytes</param>
        /// <param name="decimalCount">A number of decimal characters</param>
        /// <param name="DataType">A CLR data type</param>
        public void AddColumn(string fieldName, char fieldType, Type DataType, int fieldLength, int decimalCount)
        {
            if (fieldLength <= 0)
            {
                fieldLength = 1;
            }
            if (_dbaseColumns == null)
            {
                _dbaseColumns = new DbaseFieldDescriptor[0];
            }
            int tempLength = 1;  // the length is used for the offset, and there is a * for deleted as the first byte

            DbaseFieldDescriptor[] tempFieldDescriptors = new DbaseFieldDescriptor[_dbaseColumns.Length + 1];
            for (int i = 0; i < _dbaseColumns.Length; i++)
            {
                _dbaseColumns[i].DataAddress = tempLength;
                tempLength = tempLength + _dbaseColumns[i].Length;
                tempFieldDescriptors[i] = _dbaseColumns[i];
            }
            tempFieldDescriptors[_dbaseColumns.Length]              = new DbaseFieldDescriptor();
            tempFieldDescriptors[_dbaseColumns.Length].Length       = fieldLength;
            tempFieldDescriptors[_dbaseColumns.Length].DecimalCount = decimalCount;
            tempFieldDescriptors[_dbaseColumns.Length].DataAddress  = tempLength;

            // set the field name
            string tempFieldName = fieldName;

            if (tempFieldName == null)
            {
                tempFieldName = "NoName";
            }
            if (tempFieldName.Length > 11)
            {
                tempFieldName = tempFieldName.Substring(0, 11);
                //!!!Trace.Write("FieldName " + fieldName + " is longer than 11 characters, truncating to " + tempFieldName);
            }
            tempFieldDescriptors[_dbaseColumns.Length].Name = tempFieldName;

            // the field type
            tempFieldDescriptors[_dbaseColumns.Length].DataType = DataType;
            if ((fieldType == 'C') || (fieldType == 'c'))
            {
                tempFieldDescriptors[_dbaseColumns.Length].DbaseType = 'C';
            }
            else if ((fieldType == 'S') || (fieldType == 's'))
            {
                tempFieldDescriptors[_dbaseColumns.Length].DbaseType = 'C';
                tempFieldDescriptors[_dbaseColumns.Length].Length    = 8;
            }
            else if ((fieldType == 'D') || (fieldType == 'd'))
            {
                tempFieldDescriptors[_dbaseColumns.Length].DbaseType = 'D';
                tempFieldDescriptors[_dbaseColumns.Length].Length    = 8;
            }
            else if ((fieldType == 'F') || (fieldType == 'f'))
            {
                tempFieldDescriptors[_dbaseColumns.Length].DbaseType = 'F';
            }
            else if ((fieldType == 'N') || (fieldType == 'n'))
            {
                tempFieldDescriptors[_dbaseColumns.Length].DbaseType = 'N';
                if (decimalCount < 0)
                {
                    tempFieldDescriptors[_dbaseColumns.Length].DecimalCount = 0;
                }
                if (decimalCount > fieldLength - 1)
                {
                    tempFieldDescriptors[_dbaseColumns.Length].DecimalCount = fieldLength - 1;
                }
            }
            else if ((fieldType == 'L') || (fieldType == 'l'))
            {
                tempFieldDescriptors[_dbaseColumns.Length].DbaseType = 'L';
                tempFieldDescriptors[_dbaseColumns.Length].Length    = 1;
            }
            else
            {
                throw new NotSupportedException("Unsupported field type " + fieldType + " For column " + fieldName);
            }
            // the length of a record
            tempLength = tempLength + tempFieldDescriptors[_dbaseColumns.Length].Length;

            // set the new fields.
            _dbaseColumns = tempFieldDescriptors;
            _headerLength = 33 + 32 * _dbaseColumns.Length;
            _numFields    = _dbaseColumns.Length;
            _recordLength = tempLength;
        }
        private object readDbfValue(DbaseFieldDescriptor dbf)
        {
            byte[] bytes = _br.ReadBytes(dbf.Length);

            switch (dbf.DataType.ToString())
            {
            case "System.String":
                //if (_encoding == null)
                //    return _fileEncoding.GetString(bytes).Replace("\0", "").Trim();
                //else
                return(_dbaseHeader.Encoding.GetString(bytes).Replace("\0", "").Trim());

            case "System.Double":
                string temp = System.Text.Encoding.UTF7.GetString(bytes).Replace("\0", "").Trim();
                double dbl  = 0;
                if (double.TryParse(temp, System.Globalization.NumberStyles.Float, _numberFormat, out dbl))
                {
                    return(dbl);
                }
                else
                {
                    return(DBNull.Value);
                }

            case "System.Int16":
                string temp16 = System.Text.Encoding.UTF7.GetString((bytes)).Replace("\0", "").Trim();
                Int16  i16    = 0;
                if (Int16.TryParse(temp16, System.Globalization.NumberStyles.Float, _numberFormat, out i16))
                {
                    return(i16);
                }
                else
                {
                    return(DBNull.Value);
                }

            case "System.Int32":
                string temp32 = System.Text.Encoding.UTF7.GetString((bytes)).Replace("\0", "").Trim();
                Int32  i32    = 0;
                if (Int32.TryParse(temp32, System.Globalization.NumberStyles.Float, _numberFormat, out i32))
                {
                    return(i32);
                }
                else
                {
                    return(DBNull.Value);
                }

            case "System.Int64":
                string temp64 = System.Text.Encoding.UTF7.GetString((bytes)).Replace("\0", "").Trim();
                Int64  i64    = 0;
                if (Int64.TryParse(temp64, System.Globalization.NumberStyles.Float, _numberFormat, out i64))
                {
                    return(i64);
                }
                else
                {
                    return(DBNull.Value);
                }

            case "System.Single":
                string temp4 = System.Text.Encoding.UTF8.GetString((bytes));
                float  f     = 0;
                if (float.TryParse(temp4, System.Globalization.NumberStyles.Float, _numberFormat, out f))
                {
                    return(f);
                }
                else
                {
                    return(DBNull.Value);
                }

            case "System.Boolean":
                char tempChar = Convert.ToChar(bytes[0]);    // BitConverter.ToChar(bytes, 0);// _br.ReadChar();
                return((tempChar == 'T') || (tempChar == 't') || (tempChar == 'Y') || (tempChar == 'y'));

            case "System.DateTime":
#if !MONO
                DateTime date;
                if (DateTime.TryParseExact(System.Text.Encoding.UTF7.GetString((bytes)),
                                           "yyyyMMdd", _numberFormat, System.Globalization.DateTimeStyles.None, out date))
                {
                    return(date);
                }
                else
                {
                    return(DBNull.Value);
                }
#else // в mono еще не реализован метод DateTime.TryParseExact
                try
                {
                    return(DateTime.ParseExact(System.Text.Encoding.UTF7.GetString((bytes)),
                                               "yyyyMMdd", _numberFormat, System.Globalization.DateTimeStyles.None));
                }
                catch
                {
                    return(DBNull.Value);
                }
#endif
            default:
                throw (new NotSupportedException("Unable to process field '" + dbf.Name + "' (data type '" + dbf.DataType.ToString() + "')"));
            }
        }