Exemple #1
0
 public StarlingDbfRecord(StarlingDbfHeader head, byte[] rec)
 {
     if (0 < rec.Length && rec.Length == head.DRS)
     {
         // keep reference to .dbf header
         header = head;
         // read record status
         record_status = (@status)rec[0];
         // read contents of all fields
         field_contents = new List <byte[]>();
         uint offset = 1;
         foreach (StarlingDbfField r in header.field_structures)
         {
             byte[] ba = new byte[r.fieldlength];
             Array.Copy(rec, offset, ba, 0, r.fieldlength);
             field_contents.Add(ba);
             offset += r.fieldlength;
         }
     }
     else
     {
         throw new Exception("Wrong record size.");
     }
 }
Exemple #2
0
        /// <summary>
        /// Constructor method that opens and reads a Starling database (.dbf).
        /// </summary>
        /// <param name="dbfFilename">Filename of the Starling database to be read.</param>
        /// <param name="progressHandler">Optional event handler for progress reports.</param>
        public StarlingDbfReader(String dbfFilename, ReportProgressEventHandler progressHandler = null)
        {
            // register optional event
            if (progressHandler != null)
            {
                onProgressChanged += progressHandler;
            }

            // get var filename
            String VarFilename = Path.ChangeExtension(dbfFilename, "var");

            table_name = Path.GetFileNameWithoutExtension(dbfFilename);

            if (File.Exists(dbfFilename))
            {
                // read header with database structure
                reportProgress(0, "Reading header");
                header = new StarlingDbfHeader(dbfFilename);
                reportProgress(10, "Reading header: fields");

                // log header info
                Trace.WriteLine(dbfFilename);
                Trace.WriteLine(String.Format("DBF Filesize:\t\t{0}", header.getFileSize()));
                Trace.WriteLine(String.Format("Actual filesize:\t{0}", new FileInfo(dbfFilename).Length));
                Trace.WriteLine("Header");
                Trace.Indent();
                foreach (String s in header.ToString().Split('\n'))
                {
                    Trace.WriteLine(s);
                }
                Trace.Unindent();
                Trace.WriteLine(String.Format("Fields ({0})", header.field_structures.Count));
                Trace.Indent();

                // read field structures
                for (int i = 0; i < header.field_structures.Count; i++)
                {
                    StarlingDbfField rec = header.field_structures[i];

                    // log field info
                    Trace.WriteLine(String.Format("Field {0}", i));
                    Trace.Indent();
                    foreach (String s in rec.ToString().Split('\n'))
                    {
                        Trace.WriteLine(s);
                    }
                    Trace.Unindent();

                    // report progress
                    reportProgress(10 + 10 * ((float)i / header.field_structures.Count), "Reading header: fields");
                }
                Trace.Unindent();

                // read byte content for all records
                reportProgress(20, "Reading records");
                records = new List <StarlingDbfRecord>();
                using (BinaryReader dbfFile = new BinaryReader(File.OpenRead(dbfFilename), Encoding.ASCII))
                {
                    dbfFile.ReadBytes(header.HSZ);
                    while (dbfFile.BaseStream.Length - dbfFile.BaseStream.Position >= header.DRS)
                    {
                        StarlingDbfRecord rec = new StarlingDbfRecord(header, dbfFile.ReadBytes(header.DRS));
                        records.Add(rec);
                        reportProgress(20 + (40d * dbfFile.BaseStream.Position) / dbfFile.BaseStream.Length, "Reading records");
                    }
                }


                if (File.Exists(VarFilename))
                {
                    // in case of an accompanying .var file, replace byte content of record fields if they are pointers to data in .var file
                    // first check if we are dealing with a .dbf file and if it contains data pointers
                    bool varfile_is_needed = false;
                    if (String.Equals(Path.GetExtension(dbfFilename), ".dbf", StringComparison.OrdinalIgnoreCase))
                    {
                        for (int i = 0; i < header.field_structures.Count && !varfile_is_needed; i++)
                        {
                            StarlingDbfField fld = header.field_structures[i];
                            varfile_is_needed = (fld.type == StarlingDbfField.FieldType.character && fld.fieldlength == 6);
                        }
                    }

                    if (varfile_is_needed)
                    {
                        reportProgress(60, "Processing records");
                        using (BinaryReader varFile = new BinaryReader(File.OpenRead(VarFilename), Encoding.ASCII))
                        {
                            // walk through all fields (columns)
                            for (int i = 0; i < header.field_structures.Count; i++)
                            {
                                // check if the field contains data pointers, if so update each record's contents
                                StarlingDbfField fld = header.field_structures[i];
                                if (fld.type == StarlingDbfField.FieldType.character && fld.fieldlength == 6)
                                {
                                    /*
                                     * We are dealing with a pointer to the VAR file here.
                                     * The first 4 bytes give the position, the last 2 bytes give length.
                                     */
                                    foreach (StarlingDbfRecord rec in records)
                                    {
                                        byte[] old_content = rec.field_contents[i];
                                        if (!StarlingDbfRecord.emptyVarRef(old_content))
                                        {
                                            uint   position = BitConverter.ToUInt32(old_content, 0);
                                            ushort length   = BitConverter.ToUInt16(old_content, 4);
                                            varFile.BaseStream.Seek(position, SeekOrigin.Begin);
                                            byte[] new_content = varFile.ReadBytes(length);
                                            rec.field_contents[i] = new_content;
                                        }
                                    }
                                }
                                reportProgress(60 + (40d * i) / header.field_structures.Count, "Processing records");
                            }
                        }
                    }
                }

                reportProgress(100, "Database loaded");

                // log records
                //foreach (StarlingDbfRecord rec in records)
                //    Trace.WriteLine(rec.ToString());
            }
            else
            {
                Trace.WriteLine("DBF file not found.");
            }

            // unregister event
            if (progressHandler != null)
            {
                onProgressChanged -= progressHandler;
            }
        }