Пример #1
0
        /// <summary>
        /// Get date value.
        /// </summary>
        /// <param name="nColIndex"></param>
        /// <returns></returns>
        public void SetDateValue(int nColIndex, DateTime value)
        {
            DbfColumn ocol = mHeader[nColIndex];

            DbfColumn.DbfColumnType ocolType = ocol.ColumnType;

            if (ocolType == DbfColumn.DbfColumnType.Date)
            {
                //Format date and set value, date format is like this: yyyyMMdd
                //-------------------------------------------------------------
                encoding.GetBytes(value.ToString("yyyyMMdd"), 0, ocol.Length, mData, ocol.DataAddress);
            }
            else
            {
                throw new Exception("Invalid data type. Column is of '" + ocol.ColumnType.ToString() + "' type, not date.");
            }
        }
Пример #2
0
        protected void writeHeader()
        {
            Logger.info($"Записываем в DBF {dbfFields.Count} полей:");
            Logger.info(string.Join(", ", dbfFields.Select(x => x != null ? x.name : "[null!]").ToArray()));
            foreach (var field in dbfFields)
            {
                if (field == null)
                {
                    throw new ArgumentNullException(nameof(field));
                }
                string name    = field.name ?? throw new ArgumentNullException(nameof(field.name));
                string type    = field.type ?? throw new ArgumentNullException(nameof(field.type));
                string attrlen = field.length ?? throw new ArgumentNullException(nameof(field.type));

                DbfColumn.DbfColumnType column = DbfColumn.DbfColumnType.Character;
                if (type == "string")
                {
                    column = DbfColumn.DbfColumnType.Character;
                }
                if (type == "date")
                {
                    column = DbfColumn.DbfColumnType.Date;
                }
                if (type == "numeric")
                {
                    column = DbfColumn.DbfColumnType.Number;
                }

                var length = attrlen.Split(',');
                int nlen   = Int32.Parse(length[0]);
                int ndec   = (length.Length > 1) ? Int32.Parse(length[1]) : 0;
                odbf.Header.AddColumn(new DbfColumn(name, column, nlen, ndec));
                Logger.debug($"Записываем поле '{name}' типа '{type}' длиной {nlen},{ndec}");
            }
            odbf.WriteHeader();
        }
Пример #3
0
        /// <summary>
        /// Set string data to a column, if the string is longer than specified column length it will be truncated!
        /// If dbf column type is not a string, input will be treated as dbf column
        /// type and if longer than length an exception will be thrown.
        /// </summary>
        /// <param name="nColIndex"></param>
        /// <returns></returns>
        public string this[int nColIndex]
        {
            set
            {
                DbfColumn ocol = _header[nColIndex];
                DbfColumn.DbfColumnType ocolType = ocol.ColumnType;


                //
                //if an empty value is passed, we just clear the data, and leave it blank.
                //note: test have shown that testing for null and checking length is faster than comparing to "" empty str :)
                //------------------------------------------------------------------------------------------------------------
                if (string.IsNullOrEmpty(value))
                {
                    //this is like NULL data, set it to empty. i looked at SAS DBF output when a null value exists
                    //and empty data are output. we get the same result, so this looks good.
                    Buffer.BlockCopy(_emptyRecord, ocol.DataAddress, _data, ocol.DataAddress, ocol.Length);
                }
                else
                {
                    //set values according to data type:
                    //-------------------------------------------------------------
                    if (ocolType == DbfColumn.DbfColumnType.Character)
                    {
                        if (!_allowStringTruncate && value.Length > ocol.Length)
                        {
                            throw new DbfDataTruncateException("Value not set. String truncation would occur and AllowStringTruncate flag is set to false. To supress this exception change AllowStringTruncate to true.");
                        }

                        //BlockCopy copies bytes.  First clear the previous value, then set the new one.
                        Buffer.BlockCopy(_emptyRecord, ocol.DataAddress, _data, ocol.DataAddress, ocol.Length);
                        encoding.GetBytes(value, 0, value.Length > ocol.Length ? ocol.Length : value.Length, _data, ocol.DataAddress);
                    }
                    else if (ocolType == DbfColumn.DbfColumnType.Number)
                    {
                        if (ocol.DecimalCount == 0)
                        {
                            //integers
                            //----------------------------------

                            //throw an exception if integer overflow would occur
                            if (!_allowIntegerTruncate && value.Length > ocol.Length)
                            {
                                throw new DbfDataTruncateException("Value not set. Integer does not fit and would be truncated. AllowIntegerTruncate is set to false. To supress this exception set AllowIntegerTruncate to true, although that is not recomended.");
                            }


                            //clear all numbers, set to [space].
                            //-----------------------------------------------------
                            Buffer.BlockCopy(_emptyRecord, 0, _data, ocol.DataAddress, ocol.Length);


                            //set integer part, CAREFUL not to overflow buffer! (truncate instead)
                            //-----------------------------------------------------------------------
                            int nNumLen = value.Length > ocol.Length ? ocol.Length : value.Length;
                            encoding.GetBytes(value, 0, nNumLen, _data, (ocol.DataAddress + ocol.Length - nNumLen));
                        }
                        else
                        {
                            ///TODO: we can improve perfomance here by not using temp char arrays cDec and cNum,
                            ///simply directly copy from source string using encoding!


                            //break value down into integer and decimal portions
                            //--------------------------------------------------------------------------
                            int    nidxDecimal = value.IndexOf('.'); //index where the decimal point occurs
                            char[] cDec        = null;               //decimal portion of the number
                            char[] cNum        = null;               //integer portion

                            if (nidxDecimal > -1)
                            {
                                cDec = value.Substring(nidxDecimal + 1).Trim().ToCharArray();
                                cNum = value.Substring(0, nidxDecimal).ToCharArray();

                                //throw an exception if decimal overflow would occur
                                if (!_allowDecimalTruncate && cDec.Length > ocol.DecimalCount)
                                {
                                    throw new DbfDataTruncateException("Value not set. Decimal does not fit and would be truncated. AllowDecimalTruncate is set to false. To supress this exception set AllowDecimalTruncate to true.");
                                }
                            }
                            else
                            {
                                cNum = value.ToCharArray();
                            }


                            //throw an exception if integer overflow would occur
                            if (!_allowIntegerTruncate && cNum.Length > ocol.Length - ocol.DecimalCount - 1)
                            {
                                throw new DbfDataTruncateException("Value not set. Integer does not fit and would be truncated. AllowIntegerTruncate is set to false. To supress this exception set AllowIntegerTruncate to true, although that is not recomended.");
                            }


                            //------------------------------------------------------------------------------------------------------------------
                            // NUMERIC TYPE
                            //------------------------------------------------------------------------------------------------------------------

                            //clear all decimals, set to 0.
                            //-----------------------------------------------------
                            Buffer.BlockCopy(_decimalClear, 0, _data, (ocol.DataAddress + ocol.Length - ocol.DecimalCount), ocol.DecimalCount);

                            //clear all numbers, set to [space].
                            Buffer.BlockCopy(_emptyRecord, 0, _data, ocol.DataAddress, (ocol.Length - ocol.DecimalCount));



                            //set decimal numbers, CAREFUL not to overflow buffer! (truncate instead)
                            //-----------------------------------------------------------------------
                            if (nidxDecimal > -1)
                            {
                                int nLen = cDec.Length > ocol.DecimalCount ? ocol.DecimalCount : cDec.Length;
                                encoding.GetBytes(cDec, 0, nLen, _data, (ocol.DataAddress + ocol.Length - ocol.DecimalCount));
                            }

                            //set integer part, CAREFUL not to overflow buffer! (truncate instead)
                            //-----------------------------------------------------------------------
                            int nNumLen = cNum.Length > ocol.Length - ocol.DecimalCount - 1 ? (ocol.Length - ocol.DecimalCount - 1) : cNum.Length;
                            encoding.GetBytes(cNum, 0, nNumLen, _data, ocol.DataAddress + ocol.Length - ocol.DecimalCount - nNumLen - 1);


                            //set decimal point
                            //-----------------------------------------------------------------------
                            _data[ocol.DataAddress + ocol.Length - ocol.DecimalCount - 1] = (byte)'.';
                        }
                    }
                    else if (ocolType == DbfColumn.DbfColumnType.Float)
                    {
                        //------------------------------------------------------------------------------------------------------------------
                        // FLOAT TYPE
                        // example:   value=" 2.40000000000e+001"  Length=19   Decimal-Count=11
                        //------------------------------------------------------------------------------------------------------------------


                        // check size, throw exception if value won't fit:
                        if (value.Length > ocol.Length)
                        {
                            throw new DbfDataTruncateException("Value not set. Float value does not fit and would be truncated.");
                        }


                        double parsed_value;
                        if (!Double.TryParse(value, out parsed_value))
                        {
                            //value did not parse, input is not correct.
                            throw new DbfDataTruncateException("Value not set. Float value format is bad: '" + value + "'   expected format: ' 2.40000000000e+001'");
                        }

                        //clear value that was present previously
                        Buffer.BlockCopy(_decimalClear, 0, _data, ocol.DataAddress, ocol.Length);

                        //copy new value at location
                        char[] valueAsCharArray = value.ToCharArray();
                        encoding.GetBytes(valueAsCharArray, 0, valueAsCharArray.Length, _data, ocol.DataAddress);
                    }
                    else if (ocolType == DbfColumn.DbfColumnType.Integer)
                    {
                        //note this is a binary Integer type!
                        //----------------------------------------------

                        ///TODO: maybe there is a better way to copy 4 bytes from int to byte array. Some memory function or something.
                        _tempIntVal[0] = Convert.ToInt32(value);
                        Buffer.BlockCopy(_tempIntVal, 0, _data, ocol.DataAddress, 4);
                    }
                    else if (ocolType == DbfColumn.DbfColumnType.Memo)
                    {
                        //copy 10 digits...
                        ///TODO: implement MEMO

                        throw new NotImplementedException("Memo data type functionality not implemented yet!");
                    }
                    else if (ocolType == DbfColumn.DbfColumnType.Boolean)
                    {
                        if (String.Compare(value, "true", true) == 0 || String.Compare(value, "1", true) == 0 ||
                            String.Compare(value, "T", true) == 0 || String.Compare(value, "yes", true) == 0 ||
                            String.Compare(value, "Y", true) == 0)
                        {
                            _data[ocol.DataAddress] = (byte)'T';
                        }
                        else if (value == " " || value == "?")
                        {
                            _data[ocol.DataAddress] = (byte)'?';
                        }
                        else
                        {
                            _data[ocol.DataAddress] = (byte)'F';
                        }
                    }
                    else if (ocolType == DbfColumn.DbfColumnType.Date)
                    {
                        //try to parse out date value using Date.Parse() function, then set the value
                        DateTime dateval;
                        if (DateTime.TryParse(value, out dateval))
                        {
                            SetDateValue(nColIndex, dateval);
                        }
                        else
                        {
                            throw new InvalidOperationException("Date could not be parsed from source string! Please parse the Date and set the value (you can try using DateTime.Parse() or DateTime.TryParse() functions).");
                        }
                    }
                    else if (ocolType == DbfColumn.DbfColumnType.Binary)
                    {
                        throw new InvalidOperationException("Can not use string source to set binary data. Use SetBinaryValue() and GetBinaryValue() functions instead.");
                    }

                    else
                    {
                        throw new InvalidDataException("Unrecognized data type: " + ocolType.ToString());
                    }
                }
            }

            get
            {
                DbfColumn ocol = _header[nColIndex];
                return(new string(encoding.GetChars(_data, ocol.DataAddress, ocol.Length)));
            }
        }
Пример #4
0
 /// <summary>
 /// Create and add a new column with specified name, type, length, and decimal precision.
 /// </summary>
 /// <param name="sName">Field name. Uniqueness is not enforced.</param>
 /// <param name="type"></param>
 /// <param name="nLength">Length of the field including decimal point and decimal numbers</param>
 /// <param name="nDecimals">Number of decimal places to keep.</param>
 public void AddColumn(string sName, DbfColumn.DbfColumnType type, int nLength, int nDecimals)
 {
     AddColumn(new DbfColumn(sName, type, nLength, nDecimals));
 }
Пример #5
0
 /// <summary>
 /// Create and add a new column with specified name and type.
 /// </summary>
 /// <param name="sName"></param>
 /// <param name="type"></param>
 public void AddColumn(string sName, DbfColumn.DbfColumnType type)
 {
     AddColumn(new DbfColumn(sName, type));
 }