예제 #1
0
        private void FillVFPFields(Stream fs, DbfHeader header, DatabaseTable dbTable)
        {
            const int fieldSize = 32;

            header.Fields = new List <DbfField>();
            fs.Seek(32, SeekOrigin.Begin);
            var fieldBuf       = bufferPool.Rent(fieldSize);
            var index          = 0;
            int nullFieldIndex = -1;

            while (fs.Read(fieldBuf, 0, fieldSize) != 0 && fieldBuf[0] != FieldDescriptorTerminator)
            {
                var field = new VfpField
                {
                    Name               = encoding.GetString(fieldBuf, 0, 10).TrimEnd('\0'),
                    Type               = (char)fieldBuf[11],
                    Displacement       = BTOI(fieldBuf, 12),
                    Length             = fieldBuf[16],
                    DecimalCount       = fieldBuf[17],
                    Flags              = (DbfFieldFlags)fieldBuf[18],
                    NextAutoIncrement  = BTOI(fieldBuf, 19),
                    AutoIncrementStep  = fieldBuf[23],
                    Index              = index,
                    VarLengthSizeIndex = -1,
                    NullFieldIndex     = -1,
                };
                if (field.Type == 'V' || field.Type == 'Q')
                {
                    nullFieldIndex++;
                    field.VarLengthSizeIndex = nullFieldIndex;
                }
                if ((field.Flags & DbfFieldFlags.Null) != 0)
                {
                    nullFieldIndex++;
                    field.NullFieldIndex = nullFieldIndex;
                }
                Buffer.BlockCopy(fieldBuf, 24, field.Reserved24To31 = new byte[8], 0, 8);
                if (dbTable != null && dbTable.Fields.Count > index)
                {
                    field.Name = dbTable.Fields[index].Name;
                }
                header.Fields.Add(field);
                index++;
            }
            bufferPool.Return(fieldBuf);
        }
예제 #2
0
        private void FillBacklink(Stream fs, DbfHeader header)
        {
            const int maxBacklinkLengh = 263;

            fs.Seek(header.HeaderSize - maxBacklinkLengh, SeekOrigin.Begin);
            var fieldBuf       = bufferPool.Rent(maxBacklinkLengh);
            var read           = fs.Read(fieldBuf, 0, maxBacklinkLengh);
            var backlinkLength = read;

            if (read != 0)
            {
                var nullIdx = GetIndexOf(fieldBuf, 0, 0);
                if (nullIdx != -1)
                {
                    backlinkLength = nullIdx;
                }
            }
            header.Backlink = encoding.GetString(fieldBuf, 0, backlinkLength);
            bufferPool.Return(fieldBuf);
        }
예제 #3
0
        public DbfHeader GetHeader()
        {
            var header = new DbfHeader();

            using (var fs = OpenReadOnly())
            {
                header.Type         = (DbfType)fs.ReadByte();
                fs.Position         = 4;
                header.RecordCount  = fs.ReadInt();
                header.HeaderSize   = fs.ReadShort();
                header.RecordLength = fs.ReadShort();
                header.FileSize     = fs.Length;

                fs.Position  = 28;
                header.Flags = (DbfHeaderFlags)fs.ReadByte();

                switch (header.Type)
                {
                case DbfType.VisualFoxPro:
                case DbfType.VisualFoxProAutoInc:
                case DbfType.VisualFoxProVar:
                    DatabaseTable dbTable = null;
                    if ((header.Flags & DbfHeaderFlags.DBC) == 0)
                    {
                        FillBacklink(fs, header);
                        if (!string.IsNullOrEmpty(header.Backlink))
                        {
                            var db = Database.FromDbf(new Dbf(Path.Combine(Path.GetDirectoryName(dbfPath), header.Backlink)));
                            dbTable = db.Tables.Find(t => t.Name.Equals(Path.GetFileNameWithoutExtension(dbfPath), StringComparison.OrdinalIgnoreCase));
                        }
                    }
                    FillVFPFields(fs, header, dbTable);
                    break;

                default:
                    throw new NotSupportedException($"Field Data for DBF-Type {header.Type} is not supported.");
                }
            }

            return(header);
        }
예제 #4
0
        public DbfReader(Dbf dbf, Encoding textEncoding)
        {
            DbfTypeMap.Add('C', (i, b, f, e) =>
            {
                if (f.Length == 1)
                {
                    return(e.GetString(b)[0]);
                }
                return(e.GetString(b).TrimEnd('\0'));
            });
            DbfTypeMap.Add('M', (i, b, f, e) => BitConverter.ToInt32(b));
            DbfTypeMap.Add('W', (i, b, f, e) => BitConverter.ToInt32(b));
            DbfTypeMap.Add('G', (i, b, f, e) => BitConverter.ToInt32(b));
            DbfTypeMap.Add('Y', (i, b, f, e) => BitConverter.ToInt64(b) / 10000m); // Stored as int64 with 4 implicit decimal places
            DbfTypeMap.Add('D', (i, b, f, e) =>
            {
                var dateStr = e.GetString(b).Trim(); return(dateStr == "" ? DateTime.MinValue : DateTime.ParseExact(dateStr, "yyyyMMdd", null));
            });
            DbfTypeMap.Add('T', (i, b, f, e) => JulianDateHelper.FromULongBuffer(b));
            DbfTypeMap.Add('N', (i, b, f, e) =>
            {
                var numStr = e.GetString(b).Trim();

                if (f.DecimalCount == 0)
                {
                    if (f.Length < 3)
                    {
                        if (numStr == "")
                        {
                            return((byte)0);
                        }
                        return(byte.Parse(numStr));
                    }
                    else if (f.Length < 5)
                    {
                        if (numStr == "")
                        {
                            return((short)0);
                        }
                        return(short.Parse(numStr));
                    }
                    else if (f.Length < 10)
                    {
                        if (numStr == "")
                        {
                            return((int)0);
                        }
                        return(int.Parse(numStr));
                    }
                    else if (f.Length < 19)
                    {
                        if (numStr == "")
                        {
                            return((long)0);
                        }
                        return(long.Parse(numStr));
                    }
                }
                return(numStr == "" ? 0m : decimal.Parse(numStr));
            });
            DbfTypeMap.Add('B', (i, b, f, e) => BitConverter.ToInt32(b));
            DbfTypeMap.Add('O', (i, b, f, e) => BitConverter.ToDouble(b));
            DbfTypeMap.Add('F', (i, b, f, e) => { var numStr = e.GetString(b).Trim(); return(numStr == "" ? 0f : float.Parse(numStr)); });
            DbfTypeMap.Add('I', (i, b, f, e) => BitConverter.ToInt32(b));
            DbfTypeMap.Add('L', (i, b, f, e) => BitConverter.ToBoolean(b));
            DbfTypeMap.Add('Q', CopyFieldBuffer);
            DbfTypeMap.Add('P', CopyFieldBuffer);

            this.dbf     = dbf;
            TextEncoding = textEncoding;
            dbfHeader    = dbf.GetHeader();

            if (IsVisualFoxPro(dbfHeader))
            { // Special handling for VFP
                DbfTypeMap['B'] = (i, b, f, e) => BitConverter.ToDouble(b);

                // VarChar/VarBinary
                // SPECIAL CASE for VARCHAR/BINARY
                DbfTypeMap['V'] = (i, b, f, e) => f.Flags.HasFlag(DbfFieldFlags.Binary) ? CopyFieldBuffer(i, b, f, e) : e.GetString(b);

                // _NullFlags
                nullField            = dbfHeader.Fields.FirstOrDefault(x => x.Type == '0');
                nullFieldDataHandler = DbfTypeMap['0'] = CopyFieldBuffer;

                if (nullField != null)
                {
                    if (nullField.Length == 1)
                    {
                        nullFieldHandlerFactory = (i, b, f, e) => new UIntNullFieldHandler(b[0]);
                    }
                    else
                    {
                        nullFieldHandlerFactory = (i, b, f, e) => new BitArrayNullFieldHandler(b.ToArray());
                    }
                }
            }
        }
예제 #5
0
 private bool IsVisualFoxPro(DbfHeader dbfHeader)
 {
     return(dbfHeader.Type == DbfType.VisualFoxPro || dbfHeader.Type == DbfType.VisualFoxProVar || dbfHeader.Type == DbfType.VisualFoxProAutoInc);
 }