internal static ICollection<DbaseField> GetFields(DataTable schema, DbaseHeader header) { if (schema == null) { throw new ArgumentNullException("schema"); } List<DbaseField> fields = new List<DbaseField>(); DataView schemaView = new DataView(schema, "", ProviderSchemaHelper.ColumnOrdinalColumn, DataViewRowState.CurrentRows); int offset = 1; foreach (DataRowView rowView in schemaView) { if (String.Compare(rowView[ProviderSchemaHelper.ColumnNameColumn] as string, OidColumnName, StringComparison.InvariantCultureIgnoreCase) == 0) { continue; } string colName = rowView[ProviderSchemaHelper.ColumnNameColumn] as string; Type dataType = (Type)rowView[ProviderSchemaHelper.DataTypeColumn]; Int16 length = Convert.ToInt16(rowView[ProviderSchemaHelper.ColumnSizeColumn]); Byte decimals = Convert.ToByte(rowView[ProviderSchemaHelper.NumericPrecisionColumn]); int ordinal = Convert.ToInt32(rowView[ProviderSchemaHelper.ColumnOrdinalColumn]); DbaseField field = new DbaseField(header, colName, dataType, length, decimals, ordinal, offset); fields.Add(field); offset += field.Length; } return fields; }
internal static ICollection <DbaseField> GetFields(DataTable schema, DbaseHeader header) { if (schema == null) { throw new ArgumentNullException("schema"); } List <DbaseField> fields = new List <DbaseField>(); DataView schemaView = new DataView(schema, "", ProviderSchemaHelper.ColumnOrdinalColumn, DataViewRowState.CurrentRows); Int32 offset = 1; foreach (DataRowView rowView in schemaView) { if (String.Compare(rowView[ProviderSchemaHelper.ColumnNameColumn] as String, OidColumnName, StringComparison.InvariantCultureIgnoreCase) == 0) { continue; } String colName = rowView[ProviderSchemaHelper.ColumnNameColumn] as String; Type dataType = (Type)rowView[ProviderSchemaHelper.DataTypeColumn]; Int16 length = Convert.ToInt16(rowView[ProviderSchemaHelper.ColumnSizeColumn]); Byte decimals = Convert.ToByte(rowView[ProviderSchemaHelper.NumericPrecisionColumn]); Int32 ordinal = Convert.ToInt32(rowView[ProviderSchemaHelper.ColumnOrdinalColumn]); DbaseField field = new DbaseField(header, colName, dataType, length, decimals, ordinal, offset); fields.Add(field); offset += field.Length; } return(fields); }
internal DbaseField(DbaseHeader header, String name, Type type, Int16 length, Byte decimals, Int32 ordinal, Int32 offset) { _header = header; _columnName = name; _dataType = type; _length = length; _decimals = decimals; _ordinal = ordinal; _offset = offset; }
private void moveToRow(UInt32 row) { DbaseHeader header = _dbaseFile.Header; // Compute the position in the file stream for the requested row Int64 offset = header.HeaderLength + ((row - 1) * header.RecordLength); // Seek to the computed offset _dbaseFile.DataStream.Seek(offset, SeekOrigin.Begin); }
internal void UpdateHeader(DbaseHeader header) { _binaryWriter.Seek(1, SeekOrigin.Begin); Byte[] dateBytes = new Byte[3] { (Byte)(header.LastUpdate.Year - DbaseConstants.DbaseEpoch), (Byte)header.LastUpdate.Month, (Byte)header.LastUpdate.Day }; _binaryWriter.Write(dateBytes); _binaryWriter.Write(header.RecordCount); }
internal void WriteFullHeader(DbaseHeader header) { _binaryWriter.Seek(0, SeekOrigin.Begin); _binaryWriter.Write(DbaseConstants.DbfVersionCode); UpdateHeader(header); _binaryWriter.Write(header.HeaderLength); _binaryWriter.Write(header.RecordLength); _binaryWriter.Write(new Byte[DbaseConstants.EncodingOffset - (Int32)_binaryWriter.BaseStream.Position]); _binaryWriter.Write(header.LanguageDriver); _binaryWriter.Write(new Byte[2]); foreach (DbaseField field in header.Columns) { String colName = field.ColumnName + new String('\0', DbaseConstants.FieldNameLength); Byte[] colNameBytes = Encoding.ASCII.GetBytes(colName.Substring(0, DbaseConstants.FieldNameLength)); _binaryWriter.Write(colNameBytes); Char fieldTypeCode = DbaseSchema.GetFieldTypeCode(field.DataType); _binaryWriter.Write(fieldTypeCode); _binaryWriter.Write(0); // Address field isn't supported if (fieldTypeCode == 'N' || fieldTypeCode == 'F') { _binaryWriter.Write((Byte)field.Length); _binaryWriter.Write(field.Decimals); } else { _binaryWriter.Write((Byte)field.Length); _binaryWriter.Write((Byte)(field.Length >> 8)); } _binaryWriter.Write(new Byte[14]); } _binaryWriter.Write(DbaseConstants.HeaderTerminator); }
private void parseHeader(Stream dbfStream) { _header = DbaseHeader.ParseDbfHeader(new NondisposingStream(dbfStream)); _baseTable = DbaseSchema.GetFeatureTableForFields(_header.Columns, _geoFactory); _headerIsParsed = true; }
internal void UpdateHeader(DbaseHeader header) { _binaryWriter.Seek(1, SeekOrigin.Begin); Byte[] dateBytes = new Byte[3] { (Byte) (header.LastUpdate.Year - DbaseConstants.DbaseEpoch), (Byte) header.LastUpdate.Month, (Byte) header.LastUpdate.Day }; _binaryWriter.Write(dateBytes); _binaryWriter.Write(header.RecordCount); }
internal static DbaseHeader ParseDbfHeader(Stream dataStream) { DbaseHeader header; using (BinaryReader reader = new BinaryReader(dataStream)) { if (reader.ReadByte() != DbaseConstants.DbfVersionCode) { throw new NotSupportedException("Unsupported DBF Type"); } DateTime lastUpdate = new DateTime(reader.ReadByte() + DbaseConstants.DbaseEpoch, reader.ReadByte(), reader.ReadByte()); //Read the last update date UInt32 recordCount = reader.ReadUInt32(); // read number of records. Int16 storedHeaderLength = reader.ReadInt16(); // read length of header structure. Int16 storedRecordLength = reader.ReadInt16(); // read length of a record reader.BaseStream.Seek(DbaseConstants.EncodingOffset, SeekOrigin.Begin); //Seek to encoding flag Byte languageDriver = reader.ReadByte(); //Read and parse Language driver reader.BaseStream.Seek(DbaseConstants.ColumnDescriptionOffset, SeekOrigin.Begin); //Move past the reserved bytes Int32 numberOfColumns = (storedHeaderLength - DbaseConstants.ColumnDescriptionOffset) / DbaseConstants.ColumnDescriptionLength; // calculate the number of DataColumns in the header header = new DbaseHeader(languageDriver, lastUpdate, recordCount); DbaseField[] columns = new DbaseField[numberOfColumns]; Int32 offset = 1; for (Int32 i = 0; i < columns.Length; i++) { String colName = header.FileEncoding.GetString( reader.ReadBytes(11)).Replace("\0", "").Trim(); Char fieldtype = reader.ReadChar(); // Unused address data... reader.ReadInt32(); Int16 fieldLength = reader.ReadByte(); Byte decimals = 0; if (fieldtype == 'N' || fieldtype == 'F') { decimals = reader.ReadByte(); } else { fieldLength += (Int16)(reader.ReadByte() << 8); } Type dataType = mapFieldTypeToClrType(fieldtype, decimals, fieldLength); columns[i] = new DbaseField(header, colName, dataType, fieldLength, decimals, i, offset); offset += fieldLength; // Move stream to next field record reader.BaseStream.Seek(DbaseConstants.BytesFromEndOfDecimalInFieldRecord, SeekOrigin.Current); } header.Columns = columns; if (storedHeaderLength != header.HeaderLength) { throw new InvalidDbaseFileException( "Recorded header length doesn't equal computed header length."); } if (storedRecordLength != header.RecordLength) { throw new InvalidDbaseFileException( "Recorded record length doesn't equal computed record length."); } } return(header); }
/// <summary> /// Opens the <see cref="DbaseFile"/> on the file name /// specified in the constructor, /// with a value determining if the file is locked for /// exclusive read access or not. /// </summary> /// <exception cref="ObjectDisposedException"> /// Thrown when the method is called /// and object has been disposed. /// </exception> internal void Open(bool exclusive) { checkState(); // TODO: implement asynchronous access #if !CFBuild _dbaseFileStream = new FileStream(_filename, FileMode.OpenOrCreate, FileAccess.ReadWrite, exclusive ? FileShare.None : FileShare.Read, 4096, FileOptions.None); #else _dbaseFileStream = new FileStream(_filename, FileMode.OpenOrCreate, FileAccess.ReadWrite, exclusive ? FileShare.None : FileShare.Read, 4096); #endif _isOpen = true; if (!_headerIsParsed) //Don't read the header if it's already parsed { _header = DbaseHeader.ParseDbfHeader(new BufferingStream(DataStream)); _baseTable = DbaseSchema.GetFeatureTableForFields(_header.Columns); _headerIsParsed = true; } _writer = new DbaseWriter(this); _reader = new DbaseReader(this); }
internal static DbaseHeader ParseDbfHeader(Stream dataStream) { DbaseHeader header; using (BinaryReader reader = new BinaryReader(dataStream)) { if (reader.ReadByte() != DbaseConstants.DbfVersionCode) { throw new NotSupportedException("Unsupported DBF Type"); } DateTime lastUpdate = new DateTime(reader.ReadByte() + DbaseConstants.DbaseEpoch, reader.ReadByte(), reader.ReadByte()); //Read the last update date UInt32 recordCount = reader.ReadUInt32(); // read number of records. Int16 storedHeaderLength = reader.ReadInt16(); // read length of header structure. Int16 storedRecordLength = reader.ReadInt16(); // read length of a record reader.BaseStream.Seek(DbaseConstants.EncodingOffset, SeekOrigin.Begin); //Seek to encoding flag Byte languageDriver = reader.ReadByte(); //Read and parse Language driver reader.BaseStream.Seek(DbaseConstants.ColumnDescriptionOffset, SeekOrigin.Begin); //Move past the reserved bytes Int32 numberOfColumns = (storedHeaderLength - DbaseConstants.ColumnDescriptionOffset) / DbaseConstants.ColumnDescriptionLength; // calculate the number of DataColumns in the header header = new DbaseHeader(languageDriver, lastUpdate, recordCount); DbaseField[] columns = new DbaseField[numberOfColumns]; Int32 offset = 1; for (Int32 i = 0; i < columns.Length; i++) { String colName = header.FileEncoding.GetString( reader.ReadBytes(11)).Replace("\0", "").Trim(); Char fieldtype = reader.ReadChar(); // Unused address data... reader.ReadInt32(); Int16 fieldLength = reader.ReadByte(); Byte decimals = 0; if (fieldtype == 'N' || fieldtype == 'F') { decimals = reader.ReadByte(); } else { fieldLength += (Int16)(reader.ReadByte() << 8); } Type dataType = mapFieldTypeToClrType(fieldtype, decimals, fieldLength); columns[i] = new DbaseField(header, colName, dataType, fieldLength, decimals, i, offset); offset += fieldLength; // Move stream to next field record reader.BaseStream.Seek(DbaseConstants.BytesFromEndOfDecimalInFieldRecord, SeekOrigin.Current); } header.Columns = columns; if (storedHeaderLength != header.HeaderLength) { throw new InvalidDbaseFileException( "Recorded header length doesn't equal computed header length."); } if (storedRecordLength != header.RecordLength) { throw new InvalidDbaseFileException( "Recorded record length doesn't equal computed record length."); } } return header; }
internal void WriteRow(DataRow row) { if (row == null) { throw new ArgumentNullException("row"); } if (row.Table == null) { throw new ArgumentException("Row must be associated to a table."); } _binaryWriter.Write(DbaseConstants.NotDeletedIndicator); DbaseHeader header = _dbaseFile.Header; foreach (DbaseField column in header.Columns) { if (!row.Table.Columns.Contains(column.ColumnName) || String.Compare(column.ColumnName, DbaseSchema.OidColumnName, StringComparison.CurrentCultureIgnoreCase) == 0) { continue; } // TODO: reconsider type checking //if ((header.Columns[rowColumnIndex].DataType != row.Table.Columns[rowColumnIndex].DataType) || (header.Columns[rowColumnIndex].Length != row.Table.Columns[rowColumnIndex].MaxLength)) // throw new SchemaMismatchException(String.Format("Row doesn't match this DbaseWriter schema at column {0}", i)); switch (Type.GetTypeCode(column.DataType)) { case TypeCode.Boolean: if (row[column.ColumnName] == null || row[column.ColumnName] == DBNull.Value) { _binaryWriter.Write(DbaseConstants.BooleanNullChar); } else { writeBoolean((Boolean)row[column.ColumnName]); } break; case TypeCode.DateTime: if (row[column.ColumnName] == null || row[column.ColumnName] == DBNull.Value) { writeNullDateTime(); } else { writeDateTime((DateTime)row[column.ColumnName]); } break; case TypeCode.Single: case TypeCode.Double: if (row[column.ColumnName] == null || row[column.ColumnName] == DBNull.Value) { writeNullNumber(column.Length); } else { writeNumber(Convert.ToDouble(row[column.ColumnName]), column.Length, column.Decimals); } break; case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: if (row[column.ColumnName] == null || row[column.ColumnName] == DBNull.Value) { writeNullNumber(column.Length); } else { writeNumber(Convert.ToInt64(row[column.ColumnName]), column.Length); } break; case TypeCode.String: if (row[column.ColumnName] == null || row[column.ColumnName] == DBNull.Value) { writeNullString(column.Length); } else { object value = row[column.ColumnName]; //jd: can be a Guid if (value is string && String.IsNullOrEmpty((string)value)) { writeNullString(column.Length); } else { writeString(value is string?(string)value: value.ToString(), column.Length); } } break; case TypeCode.Char: case TypeCode.SByte: case TypeCode.Byte: case TypeCode.Decimal: case TypeCode.UInt16: case TypeCode.UInt32: case TypeCode.UInt64: case TypeCode.DBNull: case TypeCode.Empty: case TypeCode.Object: default: throw new NotSupportedException(String.Format( "Type not supported: {0}", column.DataType)); } } }