public List <Dictionary <string, object> > ReadDBFFile(Stream stream) { BinaryReader read = new BinaryReader(stream); //Read the DBF header info //The header is 32 bytes in length // Is it a type of file that I can handle? //File type: // 0x02 FoxBASE // 0x03 FoxBASE+/Dbase III plus, no memo // 0x30 Visual FoxPro // 0x31 Visual FoxPro, autoincrement enabled // 0x32 Visual FoxPro with field type Varchar or Varbinary // 0x43 dBASE IV SQL table files, no memo // 0x63 dBASE IV SQL system files, no memo // 0x83 FoxBASE+/dBASE III PLUS, with memo // 0x8B dBASE IV with memo // 0xCB dBASE IV SQL table files, with memo // 0xF5 FoxPro 2.x (or earlier) with memo // 0xE5 HiPer-Six format with SMT memo file // 0xFB FoxBASE byte fileType = read.ReadByte(); if (new byte[] { 0x02, 0x03, 0x30, 0x43, 0x63, 0x83, 0x8b, 0xcb, 0xf5, 0xfb }.Contains(fileType)) { // Skip date. read.BaseStream.Seek(3, SeekOrigin.Current); // Read useful datas... uint RecordCount = read.ReadUInt32(); ushort FirstRecord = read.ReadUInt16(); //or length of header ushort RecordLength = read.ReadUInt16(); //length of each record ushort reserved = read.ReadUInt16(); byte incompleteTransaction = read.ReadByte(); byte encryptionFlag = read.ReadByte(); uint freeRecordThread = read.ReadUInt32(); byte[] reservedForMultiUserDB = read.ReadBytes(8); byte tableFlags = read.ReadByte();//0x01 file has a structural .cdx, 0x02 file has a Memo field, 0x04 file is a database (.dbc) byte languageDriver = read.ReadByte(); ushort reserved2 = read.ReadUInt16(); //Read all the dbf fields info List <DBFField> DBFFields = new List <DBFField>(); while (read.PeekChar() != 0x0D) { //The Field info is 32 bytes in length DBFField field = new DBFField(); field.FieldName = Encoding.UTF8.GetString(read.ReadBytes(11), 0, 11).Replace("\0", "").ToLowerInvariant(); field.FieldType = read.ReadByte(); //Field type: // C – Character // Y – Currency // N – Numeric // F – Float // D – Date // T – DateTime // B – Double // I – Integer // L – Logical // M – Memo // G – General // C – Character (binary) // M – Memo (binary) // P – Picture field.FieldDataAddress = read.ReadUInt32();//Displacement of field in record field.FieldLengthInBytes = read.ReadByte(); field.NumberOfDecimalPlaces = read.ReadByte(); field.FieldFlags = read.ReadByte(); //0x01 System Column (not visible to user), //0x02 Column can store null values, //0x04 Binary column (for CHAR and MEMO only), //0x06 (0x02+0x04) When a field is NULL and binary (Integer, Currency, and Character/Memo fields), //0x0C Column is autoincrementing field.NextAutoIncrementValue = read.ReadUInt32(); field.AutoIncrementStepValue = read.ReadByte(); field.ReservedBytes = read.ReadBytes(8); DBFFields.Add(field); } byte headerTerminator = read.ReadByte();//Read the header record terminator //Read all the records now read.BaseStream.Seek(FirstRecord, SeekOrigin.Begin); List <Dictionary <string, object> > table = new List <Dictionary <string, object> >(); while (read.PeekChar() != 0x1A) { byte[] recordContent = read.ReadBytes(RecordLength); Dictionary <string, object> row = new Dictionary <string, object>(); int currentIndex = 1; foreach (DBFField field in DBFFields) { string temp = Encoding.UTF8.GetString(recordContent, currentIndex, field.FieldLengthInBytes); temp = temp.Trim(); currentIndex = currentIndex + field.FieldLengthInBytes; row.Add(field.FieldName, temp); } table.Add(row); } return(table); } else { throw new NotSupportedException("The DBF file type is not supported."); } }
public void ReadAttributes( Stream stream ) { BinaryReader read = new BinaryReader( stream ); //Read the DBF header info //The header is 32 bytes in length // Is it a type of file that I can handle? //File type: // 0x02 FoxBASE // 0x03 FoxBASE+/Dbase III plus, no memo // 0x30 Visual FoxPro // 0x31 Visual FoxPro, autoincrement enabled // 0x32 Visual FoxPro with field type Varchar or Varbinary // 0x43 dBASE IV SQL table files, no memo // 0x63 dBASE IV SQL system files, no memo // 0x83 FoxBASE+/dBASE III PLUS, with memo // 0x8B dBASE IV with memo // 0xCB dBASE IV SQL table files, with memo // 0xF5 FoxPro 2.x (or earlier) with memo // 0xE5 HiPer-Six format with SMT memo file // 0xFB FoxBASE byte fileType = read.ReadByte(); if( new byte[] { 0x02, 0x03, 0x30, 0x43, 0x63, 0x83, 0x8b, 0xcb, 0xf5, 0xfb }.Contains( fileType ) ) { // Skip date. read.BaseStream.Seek( 3, SeekOrigin.Current ); // Read useful datas... uint RecordCount = read.ReadUInt32(); ushort FirstRecord = read.ReadUInt16();//or length of header ushort RecordLength = read.ReadUInt16();//length of each record ushort reserved = read.ReadUInt16(); byte incompleteTransaction = read.ReadByte(); byte encryptionFlag = read.ReadByte(); uint freeRecordThread = read.ReadUInt32(); byte[] reservedForMultiUserDB = read.ReadBytes( 8 ); byte tableFlags = read.ReadByte();//0x01 file has a structural .cdx, 0x02 file has a Memo field, 0x04 file is a database (.dbc) byte languageDriver = read.ReadByte(); ushort reserved2 = read.ReadUInt16(); if( RecordCount != records.Count ) throw new InvalidOperationException( "The number of records in the DBF files does not match the number of records in the SHP file." ); //Read all the dbf fields info List<DBFField> DBFFields = new List<DBFField>(); while( read.PeekChar() != 0x0D ) { //The Field info is 32 bytes in length DBFField field = new DBFField(); field.FieldName = Encoding.UTF8.GetString( read.ReadBytes( 11 ), 0, 11 ).Replace( "\0", "" ).ToLower(); field.FieldType = read.ReadByte(); //Field type: // C – Character // Y – Currency // N – Numeric // F – Float // D – Date // T – DateTime // B – Double // I – Integer // L – Logical // M – Memo // G – General // C – Character (binary) // M – Memo (binary) // P – Picture field.FieldDataAddress = read.ReadUInt32();//Displacement of field in record field.FieldLengthInBytes = read.ReadByte(); field.NumberOfDecimalPlaces = read.ReadByte(); field.FieldFlags = read.ReadByte(); //0x01 System Column (not visible to user), //0x02 Column can store null values, //0x04 Binary column (for CHAR and MEMO only), //0x06 (0x02+0x04) When a field is NULL and binary (Integer, Currency, and Character/Memo fields), //0x0C Column is autoincrementing field.NextAutoIncrementValue = read.ReadUInt32(); field.AutoIncrementStepValue = read.ReadByte(); field.ReservedBytes = read.ReadBytes( 8 ); DBFFields.Add( field ); } byte headerTerminator = read.ReadByte();//Read the header record terminator //Read all the records now read.BaseStream.Seek( FirstRecord, SeekOrigin.Begin ); int recordIndex = 0; while(read.PeekChar() != 0x1A) { byte[] recordContent = read.ReadBytes( RecordLength ); Dictionary<string, object> row = new Dictionary<string, object>(); int currentIndex = 1; foreach( DBFField field in DBFFields ) { string temp = Encoding.UTF8.GetString( recordContent, currentIndex, field.FieldLengthInBytes ); currentIndex = currentIndex + field.FieldLengthInBytes; row.Add( field.FieldName, temp ); } this.records[ recordIndex ].Attributes = row; recordIndex++; } } else { return; } }