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."); } }
/// <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; } }