public DbaseWriter(string filename) { _dbaseFileStream = File.Open(filename, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read); _dbaseWriter = new BinaryWriter(_dbaseFileStream, Encoding.ASCII); _dbaseReader = new BinaryReader(_dbaseFileStream); if (_dbaseFileStream.Length > 0) { _header = DbaseHeader.ParseDbfHeader(_dbaseReader); _schema = DbaseSchema.GetFeatureTableForFields(_header.Columns); } }
internal static DbaseHeader ParseDbfHeader(BinaryReader reader) { DbaseHeader header = new DbaseHeader(); if (reader.ReadByte() != DbaseConstants.DbfVersionCode) { throw new NotSupportedException("Unsupported DBF Type"); } header.LastUpdate = new DateTime((int)reader.ReadByte() + 1900, (int)reader.ReadByte(), (int)reader.ReadByte()); //Read the last update date header.RecordCount = reader.ReadUInt32(); // read number of records. short storedHeaderLength = reader.ReadInt16(); // read length of header structure. short storedRecordLength = reader.ReadInt16(); // read length of a record reader.BaseStream.Seek(DbaseConstants.EncodingOffset, SeekOrigin.Begin); //Seek to encoding flag header.LanguageDriver = reader.ReadByte(); //Read and parse Language driver reader.BaseStream.Seek(DbaseConstants.ColumnDescriptionOffset, SeekOrigin.Begin); //Move past the reserved bytes int numberOfColumns = (storedHeaderLength - DbaseConstants.ColumnDescriptionOffset) / DbaseConstants.ColumnDescriptionLength; // calculate the number of DataColumns in the header DbaseField[] columns = new DbaseField[numberOfColumns]; for (int i = 0; i < columns.Length; i++) { columns[i] = new DbaseField(); columns[i].ColumnName = System.Text.Encoding.UTF7.GetString((reader.ReadBytes(11))).Replace("\0", "").Trim(); char fieldtype = reader.ReadChar(); columns[i].Address = reader.ReadInt32(); short fieldLength = reader.ReadByte(); if (fieldtype == 'N' || fieldtype == 'F') { columns[i].Decimals = reader.ReadByte(); } else { fieldLength += (short)((short)reader.ReadByte() << 8); } columns[i].Length = fieldLength; switch (fieldtype) { case 'L': columns[i].DataType = typeof(bool); break; case 'C': columns[i].DataType = typeof(string); break; case 'D': columns[i].DataType = typeof(DateTime); break; case 'N': //If the number doesn't have any decimals, make the type an integer, if possible if (columns[i].Decimals == 0) { if (columns[i].Length <= 4) { columns[i].DataType = typeof(Int16); } else if (columns[i].Length <= 9) { columns[i].DataType = typeof(Int32); } else if (columns[i].Length <= 18) { columns[i].DataType = typeof(Int64); } else { columns[i].DataType = typeof(double); } } else { columns[i].DataType = typeof(double); } break; case 'F': columns[i].DataType = typeof(float); break; case 'B': columns[i].DataType = typeof(byte[]); break; default: throw new NotSupportedException("Invalid or unknown DBase field type '" + fieldtype + "' in column '" + columns[i].ColumnName + "'"); } // Move stream to next field record reader.BaseStream.Seek(DbaseConstants.BytesFromEndOfDecimalInFieldRecord, SeekOrigin.Current); } header.Columns = columns; if (storedHeaderLength != header.HeaderLength) { throw new Exception("Recorded header length doesn't equal computed header length"); } if (storedRecordLength != header.RecordLength) { throw new Exception("Recorded record length doesn't equal computed record length"); } return(header); }