/// <summary> /// /// </summary> /// <returns></returns> public static DbaseFieldDescriptor ShapeField() { DbaseFieldDescriptor shpfield = new DbaseFieldDescriptor(); shpfield.Name="Geometry"; shpfield._type='B'; return shpfield; }
/// <summary> /// /// </summary> /// <param name="type"></param> /// <returns></returns> public static char GetDbaseType(Type type) { DbaseFieldDescriptor dbaseColumn = new DbaseFieldDescriptor(); if (type == typeof(Char)) return 'C'; if (type == typeof(string)) return 'C'; else if (type == typeof(Double)) return 'N'; else if (type == typeof(Single)) return 'N'; else if (type == typeof(Int16)) return 'N'; else if (type == typeof(Int32)) return 'N'; else if (type == typeof(Int64)) return 'N'; else if (type == typeof(UInt16)) return 'N'; else if (type == typeof(UInt32)) return 'N'; else if (type == typeof(UInt64)) return 'N'; else if (type == typeof(Decimal)) return 'N'; else if (type == typeof(Boolean)) return 'L'; else if (type == typeof(DateTime)) return 'D'; throw new NotSupportedException(String.Format("{0} does not have a corresponding dbase type.", type.Name)); }
/// <summary> /// Initializes a new instance of the ShapefileDataReader class. /// </summary> /// <param name="filename">The shapefile to read (minus the .shp extension)</param> ///<param name="geometryFactory">The GeometryFactory to use.</param> public ShapefileDataReader(string filename, IGeometryFactory geometryFactory) { if (String.IsNullOrEmpty(filename)) { throw new ArgumentNullException("filename"); } if (geometryFactory == null) { throw new ArgumentNullException("geometryFactory"); } _open = true; string dbfFile = Path.ChangeExtension(filename, "dbf"); _dbfReader = new DbaseFileReader(dbfFile); string shpFile = Path.ChangeExtension(filename, "shp"); _shpReader = new ShapefileReader(shpFile, geometryFactory); _dbfHeader = _dbfReader.GetHeader(); _recordCount = _dbfHeader.NumRecords; // copy dbase fields to our own array. Insert into the first position, the shape column _dbaseFields = new DbaseFieldDescriptor[_dbfHeader.Fields.Length + 1]; _dbaseFields[0] = DbaseFieldDescriptor.ShapeField(); for (int i = 0; i < _dbfHeader.Fields.Length; i++) { _dbaseFields[i + 1] = _dbfHeader.Fields[i]; } _shpHeader = _shpReader.Header; _dbfEnumerator = _dbfReader.GetEnumerator(); _shpEnumerator = _shpReader.GetEnumerator(); _moreRecords = true; }
/// <summary> /// /// </summary> /// <returns></returns> public static DbaseFieldDescriptor IdField() { DbaseFieldDescriptor shpfield = new DbaseFieldDescriptor(); shpfield.Name="Row"; shpfield._type='I'; return shpfield; }
public ShapefileDataReader(IStreamProviderRegistry streamProviderRegistry, IGeometryFactory geometryFactory) { if (streamProviderRegistry == null) { throw new ArgumentNullException("streamProviderRegistry"); } if (geometryFactory == null) { throw new ArgumentNullException("geometryFactory"); } _open = true; _dbfReader = new DbaseFileReader(streamProviderRegistry); _shpReader = new ShapefileReader(streamProviderRegistry, geometryFactory); _dbfHeader = _dbfReader.GetHeader(); _recordCount = _dbfHeader.NumRecords; // copy dbase fields to our own array. Insert into the first position, the shape column _dbaseFields = new DbaseFieldDescriptor[_dbfHeader.Fields.Length + 1]; _dbaseFields[0] = DbaseFieldDescriptor.ShapeField(); for (int i = 0; i < _dbfHeader.Fields.Length; i++) { _dbaseFields[i + 1] = _dbfHeader.Fields[i]; } _shpHeader = _shpReader.Header; _dbfEnumerator = _dbfReader.GetEnumerator(); _shpEnumerator = _shpReader.GetEnumerator(); _moreRecords = true; }
/// <summary> /// /// </summary> /// <param name="type"></param> /// <returns></returns> public static char GetDbaseType(Type type) { DbaseFieldDescriptor dbaseColumn = new DbaseFieldDescriptor(); if (type == typeof(Char)) { return('C'); } if (type == typeof(string)) { return('C'); } else if (type == typeof(Double)) { return('N'); } else if (type == typeof(Single)) { return('N'); } else if (type == typeof(Int16)) { return('N'); } else if (type == typeof(Int32)) { return('N'); } else if (type == typeof(Int64)) { return('N'); } else if (type == typeof(UInt16)) { return('N'); } else if (type == typeof(UInt32)) { return('N'); } else if (type == typeof(UInt64)) { return('N'); } else if (type == typeof(Decimal)) { return('N'); } else if (type == typeof(Boolean)) { return('L'); } else if (type == typeof(DateTime)) { return('D'); } throw new NotSupportedException(String.Format("{0} does not have a corresponding dbase type.", type.Name)); }
/// <summary> /// /// </summary> /// <returns></returns> public static DbaseFieldDescriptor ShapeField() { DbaseFieldDescriptor shpfield = new DbaseFieldDescriptor(); shpfield.Name = "Geometry"; shpfield._type = 'B'; return(shpfield); }
/// <summary> /// /// </summary> /// <returns></returns> public static DbaseFieldDescriptor IdField() { DbaseFieldDescriptor shpfield = new DbaseFieldDescriptor(); shpfield.Name = "Row"; shpfield._type = 'I'; return(shpfield); }
public static DbaseFileHeader GetHeader(DbaseFieldDescriptor[] dbFields, int count) { DbaseFileHeader header = new DbaseFileHeader(); header.NumRecords = count; foreach (DbaseFieldDescriptor dbField in dbFields) header.AddColumn(dbField.Name, dbField.DbaseType, dbField.Length, dbField.DecimalCount); return header; }
/// <summary> /// Initializes a new instance of the ShapefileDataReader class. /// </summary> /// <param name="filename">The shapefile to read (minus the .shp extension)</param> ///<param name="geometryFactory">The GeometryFactory to use.</param> public ShapeMemoryStreamDataReader(Stream shpStream, Stream dbfStream, IGeometryFactory geometryFactory) { if (shpStream == null) { throw new ArgumentNullException("shpStream"); } if (dbfStream == null) { throw new ArgumentNullException("dbfStream"); } if (geometryFactory == null) { throw new ArgumentNullException("geometryFactory"); } _open = true; //if (filename.ToLower().EndsWith(".shp")) // filename = filename.ToLower().Replace(".shp", String.Empty); _shpReader = new ShapeMemoryStreamReader(shpStream, geometryFactory); _dbfReader = new DbaseMemoryStreamReader(dbfStream); //_dbfReader = new DbaseFileReader(filename + ".dbf"); //_shpReader = new ShapefileReader(filename + ".shp", geometryFactory); _dbfHeader = _dbfReader.GetHeader(); _recordCount = _dbfHeader.NumRecords; // copy dbase fields to our own array. Insert into the first position, the shape column _dbaseFields = new DbaseFieldDescriptor[_dbfHeader.Fields.Length + 1]; _dbaseFields[0] = DbaseFieldDescriptor.ShapeField(); for (int i = 0; i < _dbfHeader.Fields.Length; i++) { _dbaseFields[i + 1] = _dbfHeader.Fields[i]; } _shpHeader = _shpReader.Header; _dbfEnumerator = _dbfReader.GetEnumerator(); _shpEnumerator = _shpReader.GetEnumerator(); _moreRecords = true; }
/// <summary> /// Remove a column from this DbaseFileHeader. /// </summary> /// <param name="fieldName"></param> /// <returns>return index of the removed column, -1 if no found.</returns> public int RemoveColumn(string fieldName) { int retCol = -1; int tempLength = 1; DbaseFieldDescriptor[] tempFieldDescriptors = new DbaseFieldDescriptor[_fieldDescriptions.Length - 1]; for (int i = 0, j = 0; i < _fieldDescriptions.Length; i++) { if (fieldName.ToLower() != (_fieldDescriptions[i].Name.Trim().ToLower())) { // if this is the last field and we still haven't found the // named field if (i == j && i == _fieldDescriptions.Length - 1) { return(retCol); } tempFieldDescriptors[j] = _fieldDescriptions[i]; tempFieldDescriptors[j].DataAddress = tempLength; tempLength += tempFieldDescriptors[j].Length; // only increment j on non-matching fields j++; } else { retCol = i; } } // set the new fields. _fieldDescriptions = tempFieldDescriptors; _headerLength = 33 + 32 * _fieldDescriptions.Length; _numFields = _fieldDescriptions.Length; _recordLength = tempLength; return(retCol); }
/// <summary> /// Read the header data from the DBF file. /// </summary> /// <param name="reader">BinaryReader containing the header.</param> /// <param name="cpgStreamProvider">A stream provider to read the contents of the CPG Encoding</param> public void ReadHeader(BinaryReader reader, IStreamProvider cpgStreamProvider) { // type of reader. _fileType = reader.ReadByte(); if (_fileType != 0x03) { throw new NotSupportedException("Unsupported DBF reader Type " + _fileType); } // parse the update date information. int year = reader.ReadByte(); int month = reader.ReadByte(); int day = reader.ReadByte(); _updateDate = new DateTime(year + 1900, month, day); // read the number of records. _numRecords = reader.ReadInt32(); // read the length of the header structure. _headerLength = reader.ReadInt16(); // read the length of a record _recordLength = reader.ReadInt16(); // skip the reserved bytes in the header. //in.skipBytes(20); byte[] data = reader.ReadBytes(20); byte ldid = data[29 - 12]; //get the 29th byte in the file... we've first to read into arry was no 12 var encoding = DetectEncoding(ldid, cpgStreamProvider); if (_encoding == null) { _encoding = encoding; } //Replace reader with one with correct encoding.. reader = new BinaryReader(reader.BaseStream, _encoding); // calculate the number of Fields in the header _numFields = (_headerLength - FileDescriptorSize - 1) / FileDescriptorSize; // read all of the header records _fieldDescriptions = new DbaseFieldDescriptor[_numFields]; for (int i = 0; i < _numFields; i++) { _fieldDescriptions[i] = new DbaseFieldDescriptor(); // read the field name byte[] buffer = reader.ReadBytes(11); // NOTE: only this _encoding.GetString method is available in Silverlight string name = DbaseEncodingUtility.Latin1.GetString(buffer, 0, buffer.Length); int nullPoint = name.IndexOf((char)0); if (nullPoint != -1) { name = name.Substring(0, nullPoint); } _fieldDescriptions[i].Name = name; // read the field type _fieldDescriptions[i].DbaseType = (char)reader.ReadByte(); // read the field data address, offset from the start of the record. _fieldDescriptions[i].DataAddress = reader.ReadInt32(); // read the field length in bytes int tempLength = reader.ReadByte(); if (tempLength < 0) { tempLength = tempLength + 256; } _fieldDescriptions[i].Length = tempLength; // read the field decimal count in bytes _fieldDescriptions[i].DecimalCount = reader.ReadByte(); // read the reserved bytes. //reader.skipBytes(14); reader.ReadBytes(14); } // Last byte is a marker for the end of the field definitions. // Trond Benum: This fails for some presumeably valid test shapefiles, so I have commented it out. /*byte lastByte = */ reader.ReadByte();//s(1)[0]; // if (lastByte != 0x0d) // throw new ShapefileException("DBase Header is not terminated"); // Assure we are at the end of the header! if (reader.BaseStream.Position != _headerLength) { reader.BaseStream.Seek(_headerLength, SeekOrigin.Begin); } }
/// <summary> /// Add a column to this DbaseFileHeader. /// </summary> /// <param name="fieldName">The name of the field to add.</param> /// <param name="fieldType">The type is one of (C N L or D) character, number, logical(true/false), or date.</param> /// <param name="fieldLength"> The Field length is the total length in bytes reserved for this column.</param> /// <param name="decimalCount">The decimal count only applies to numbers(N), and floating point values (F), and refers to the number of characters to reserve after the decimal point.</param> public void AddColumn(string fieldName, char fieldType, int fieldLength, int decimalCount) { if (Encoding == null) { //throw new InvalidOperationException("Must not add columns when the Encoding is not set"); Encoding = DefaultEncoding; } if (fieldLength <= 0) { fieldLength = 1; } int tempLength = 1; // the length is used for the offset, and there is a * for deleted as the first byte DbaseFieldDescriptor[] tempFieldDescriptors = new DbaseFieldDescriptor[_fieldDescriptions.Length + 1]; for (int i = 0; i < _fieldDescriptions.Length; i++) { _fieldDescriptions[i].DataAddress = tempLength; tempLength = tempLength + _fieldDescriptions[i].Length; tempFieldDescriptors[i] = _fieldDescriptions[i]; } tempFieldDescriptors[_fieldDescriptions.Length] = new DbaseFieldDescriptor(); tempFieldDescriptors[_fieldDescriptions.Length].Length = fieldLength; tempFieldDescriptors[_fieldDescriptions.Length].DecimalCount = decimalCount; tempFieldDescriptors[_fieldDescriptions.Length].DataAddress = tempLength; // set the field name string tempFieldName = fieldName; if (tempFieldName == null) { tempFieldName = "NoName"; } if (tempFieldName.Length > FieldNameMaxLength) { string s = String.Format("FieldName {0} is longer than {1} characters", fieldName, FieldNameMaxLength); throw new ArgumentException(s); } tempFieldDescriptors[_fieldDescriptions.Length].Name = tempFieldName; // the field type switch (fieldType) { case 'C': case 'c': tempFieldDescriptors[_fieldDescriptions.Length].DbaseType = 'C'; if (fieldLength > 254) { Trace.WriteLine("Field Length for " + fieldName + " set to " + fieldLength + " Which is longer than 254, not consistent with dbase III"); } break; case 'S': case 's': tempFieldDescriptors[_fieldDescriptions.Length].DbaseType = 'C'; Trace.WriteLine("Field type for " + fieldName + " set to S which is flat out wrong people!, I am setting this to C, in the hopes you meant character."); if (fieldLength > 254) { Trace.WriteLine("Field Length for " + fieldName + " set to " + fieldLength + " Which is longer than 254, not consistent with dbase III"); } tempFieldDescriptors[_fieldDescriptions.Length].Length = 8; break; case 'D': case 'd': tempFieldDescriptors[_fieldDescriptions.Length].DbaseType = 'D'; if (fieldLength != 8) { Trace.WriteLine("Field Length for " + fieldName + " set to " + fieldLength + " Setting to 8 digets YYYYMMDD"); } tempFieldDescriptors[_fieldDescriptions.Length].Length = 8; break; case 'F': case 'f': tempFieldDescriptors[_fieldDescriptions.Length].DbaseType = 'F'; if (fieldLength > 20) { Trace.WriteLine("Field Length for " + fieldName + " set to " + fieldLength + " Preserving length, but should be set to Max of 20 not valid for dbase IV, and UP specification, not present in dbaseIII."); } break; case 'N': case 'n': tempFieldDescriptors[_fieldDescriptions.Length].DbaseType = 'N'; if (fieldLength > 18) { Trace.WriteLine("Field Length for " + fieldName + " set to " + fieldLength + " Preserving length, but should be set to Max of 18 for dbase III specification."); } if (decimalCount < 0) { Trace.WriteLine("Field Decimal Position for " + fieldName + " set to " + decimalCount + " Setting to 0 no decimal data will be saved."); tempFieldDescriptors[_fieldDescriptions.Length].DecimalCount = 0; } if (decimalCount > fieldLength - 1) { Trace.WriteLine("Field Decimal Position for " + fieldName + " set to " + decimalCount + " Setting to " + (fieldLength - 1) + " no non decimal data will be saved."); tempFieldDescriptors[_fieldDescriptions.Length].DecimalCount = fieldLength - 1; } break; case 'L': case 'l': tempFieldDescriptors[_fieldDescriptions.Length].DbaseType = 'L'; if (fieldLength != 1) { Trace.WriteLine("Field Length for " + fieldName + " set to " + fieldLength + " Setting to length of 1 for logical fields."); } tempFieldDescriptors[_fieldDescriptions.Length].Length = 1; break; default: throw new NotSupportedException("Unsupported field type " + fieldType + " For column " + fieldName); } // the length of a record tempLength = tempLength + tempFieldDescriptors[_fieldDescriptions.Length].Length; // set the new fields. _fieldDescriptions = tempFieldDescriptors; _headerLength = 33 + 32 * _fieldDescriptions.Length; _numFields = _fieldDescriptions.Length; _recordLength = tempLength; }
/// <summary> /// /// </summary> /// <param name="columnValues"></param> public void Write(IList columnValues) { if (columnValues == null) { throw new ArgumentNullException("columnValues"); } if (!_headerWritten) { throw new InvalidOperationException("Header records need to be written first."); } int i = 0; _writer.Write((byte)0x20); // the deleted flag foreach (object columnValue in columnValues) { DbaseFieldDescriptor headerField = _header.Fields[i]; if (columnValue == null || columnValue == DBNull.Value) { // Don't corrupt the file by not writing if the value is null. // Instead, treat it like an empty string. Write(string.Empty, headerField.Length); } else if (headerField.Type == typeof(string)) { // If the column is a character column, the values in that // column should be treated as text, even if the column value // is not a string. Write(columnValue.ToString(), headerField.Length); } else if (IsRealType(columnValue.GetType())) { Write(Convert.ToDecimal(columnValue), headerField.Length, headerField.DecimalCount); } else if (IsIntegerType(columnValue.GetType())) { Write(Convert.ToDecimal(columnValue), headerField.Length, headerField.DecimalCount); } else if (columnValue is Decimal) { Write((decimal)columnValue, headerField.Length, headerField.DecimalCount); } else if (columnValue is Boolean) { Write((bool)columnValue); } else if (columnValue is string) { Write((string)columnValue, headerField.Length); } else if (columnValue is DateTime) { Write((DateTime)columnValue); } else if (columnValue is Char) { Write((Char)columnValue, headerField.Length); } i++; } }
/// <summary> /// Initializes a new instance of the ColumnStructure class. /// </summary> /// <param name="dbaseField"></param> /// <param name="index"></param> public ColumnStructure(DbaseFieldDescriptor dbaseField, int index) : base(dbaseField.Name, null) { _dbaseField = dbaseField; _index=index; }
/// <summary> /// Read the header data from the DBF file. /// </summary> /// <param name="reader">BinaryReader containing the header.</param> /// <param name="filename">Filename </param> public void ReadHeader(BinaryReader reader, string filename) { // type of reader. _fileType = reader.ReadByte(); if (_fileType != 0x03) throw new NotSupportedException("Unsupported DBF reader Type " + _fileType); // parse the update date information. int year = reader.ReadByte(); int month = reader.ReadByte(); int day = reader.ReadByte(); _updateDate = new DateTime(year + 1900, month, day); // read the number of records. _numRecords = reader.ReadInt32(); // read the length of the header structure. _headerLength = reader.ReadInt16(); // read the length of a record _recordLength = reader.ReadInt16(); // skip the reserved bytes in the header. //in.skipBytes(20); byte[] data = reader.ReadBytes(20); byte lcid = data[29 - 12]; //get the 29th byte in the file... we've first to read into arry was no 12 _encoding = DetectEncodingFromMark(lcid, filename); //Replace reader with one with correct encoding.. reader = new BinaryReader(reader.BaseStream, _encoding); // calculate the number of Fields in the header _numFields = (_headerLength - FileDescriptorSize - 1) / FileDescriptorSize; // read all of the header records _fieldDescriptions = new DbaseFieldDescriptor[_numFields]; for (int i = 0; i < _numFields; i++) { _fieldDescriptions[i] = new DbaseFieldDescriptor(); // read the field name byte[] buffer = reader.ReadBytes(11); // NOTE: only this _encoding.GetString method is available in Silverlight String name = _encoding.GetString(buffer, 0, buffer.Length); int nullPoint = name.IndexOf((char)0); if (nullPoint != -1) name = name.Substring(0, nullPoint); _fieldDescriptions[i].Name = name; // read the field type _fieldDescriptions[i].DbaseType = (char)reader.ReadByte(); // read the field data address, offset from the start of the record. _fieldDescriptions[i].DataAddress = reader.ReadInt32(); // read the field length in bytes int tempLength = reader.ReadByte(); if (tempLength < 0) tempLength = tempLength + 256; _fieldDescriptions[i].Length = tempLength; // read the field decimal count in bytes _fieldDescriptions[i].DecimalCount = reader.ReadByte(); // read the reserved bytes. //reader.skipBytes(14); reader.ReadBytes(14); } // Last byte is a marker for the end of the field definitions. // Trond Benum: This fails for some presumeably valid test shapefiles, so I have commented it out. byte lastByte = reader.ReadBytes(1)[0]; // if (lastByte != 0x0d) // throw new ShapefileException("DBase Header is not terminated"); // Assure we are at the end of the header! if (reader.BaseStream.Position != _headerLength) reader.BaseStream.Seek(_headerLength, SeekOrigin.Begin); }
/// <summary> /// Read the header data from the DBF file. /// </summary> /// <param name="reader">BinaryReader containing the header.</param> public void ReadHeader(BinaryReader reader) { // type of reader. _fileType = reader.ReadByte(); if (_fileType != 0x03) { throw new NotSupportedException("Unsupported DBF reader Type " + _fileType); } // parse the update date information. int year = (int)reader.ReadByte(); int month = (int)reader.ReadByte(); int day = (int)reader.ReadByte(); _updateDate = new DateTime(year + 1900, month, day); // read the number of records. _numRecords = reader.ReadInt32(); // read the length of the header structure. _headerLength = reader.ReadInt16(); // read the length of a record _recordLength = reader.ReadInt16(); // skip the reserved bytes in the header. //in.skipBytes(20); reader.ReadBytes(20); // calculate the number of Fields in the header _numFields = (_headerLength - FileDescriptorSize - 1) / FileDescriptorSize; // read all of the header records _fieldDescriptions = new DbaseFieldDescriptor[_numFields]; for (int i = 0; i < _numFields; i++) { _fieldDescriptions[i] = new DbaseFieldDescriptor(); // read the field name char[] buffer = new char[11]; buffer = reader.ReadChars(11); string name = new string(buffer); int nullPoint = name.IndexOf((char)0); if (nullPoint != -1) { name = name.Substring(0, nullPoint); } _fieldDescriptions[i].Name = name; // read the field type _fieldDescriptions[i].DbaseType = (char)reader.ReadByte(); // read the field data address, offset from the start of the record. _fieldDescriptions[i].DataAddress = reader.ReadInt32(); // read the field length in bytes int tempLength = (int)reader.ReadByte(); if (tempLength < 0) { tempLength = tempLength + 256; } _fieldDescriptions[i].Length = tempLength; // read the field decimal count in bytes _fieldDescriptions[i].DecimalCount = (int)reader.ReadByte(); // read the reserved bytes. //reader.skipBytes(14); reader.ReadBytes(14); } // Last byte is a marker for the end of the field definitions. if (reader.ReadBytes(1)[0] != 0x0d) { throw new ShapefileException("DBase Header is not terminated"); } // Assure we are at the end of the header! if (reader.BaseStream.Position != _headerLength) { reader.BaseStream.Seek(_headerLength, SeekOrigin.Begin); } }
/// <summary> /// /// </summary> /// <param name="dbaseFields"></param> /// <param name="columnValues"></param> public RowStructure(DbaseFieldDescriptor[] dbaseFields, ArrayList columnValues) { _dbaseFields = dbaseFields; _columnValues = columnValues; }
/// <summary> /// Write the enumeration of features to shapefile (shp, shx and dbf) /// </summary> /// <param name="filename">Filename to create</param> /// <param name="features">Enumeration of features to write, features will be enumerated once</param> /// <param name="fields">Fields that should be written, only those attributes specified here will be mapped from the feature attributetable while writing</param> /// <param name="shapeGeometryType">Type of geometries shapefile</param> /// <param name="dbfEncoding">Optional Encoding to be used when writing the DBF-file (default Windows-1252)</param> public static void WriteFeatures(string filename, IEnumerable<IFeature> features, DbaseFieldDescriptor[] fields, ShapeGeometryType shapeGeometryType, Encoding dbfEncoding = null) { // Set default encoding if not specified if (dbfEncoding == null) dbfEncoding = Encoding.GetEncoding(1252); // Open shapefile and dbase stream writers using (var shpWriter = new ShapefileWriter(Path.ChangeExtension(filename, ".shp"), shapeGeometryType)) { using (var dbfWriter = new DbaseFileWriter(Path.ChangeExtension(filename, ".dbf"), dbfEncoding)) { var dbfHeader = new DbaseFileHeader(dbfEncoding); foreach (var field in fields) { dbfHeader.AddColumn(field.Name, field.DbaseType, field.Length, field.DecimalCount); } dbfWriter.Write(dbfHeader); var numFeatures = 0; foreach (var feature in features) { shpWriter.Write(feature.Geometry); var values = new object[fields.Length]; for (var i = 0; i < fields.Length; i++) { values[i] = feature.Attributes[fields[i].Name]; } dbfWriter.Write(values); numFeatures++; } // set the number of records dbfHeader.NumRecords = numFeatures; // Update the header dbfWriter.Write(dbfHeader); // write the end of dbase file marker dbfWriter.WriteEndOfDbf(); // close the dbase stream dbfWriter.Close(); } } }
/// <summary> /// Initializes a new instance of the ColumnStructure class. /// </summary> /// <param name="dbaseField"></param> /// <param name="index"></param> public ColumnStructure(DbaseFieldDescriptor dbaseField, int index) : base(dbaseField.Name, null) { _dbaseField = dbaseField; _index = index; }
/// <summary> /// Add a column to this DbaseFileHeader. /// </summary> /// <param name="fieldName">The name of the field to add.</param> /// <param name="fieldType">The type is one of (C N L or D) character, number, logical(true/false), or date.</param> /// <param name="fieldLength"> The Field length is the total length in bytes reserved for this column.</param> /// <param name="decimalCount">The decimal count only applies to numbers(N), and floating point values (F), and refers to the number of characters to reserve after the decimal point.</param> public void AddColumn(string fieldName, char fieldType, int fieldLength, int decimalCount) { if (fieldLength <= 0) fieldLength = 1; if (_fieldDescriptions == null) _fieldDescriptions = new DbaseFieldDescriptor[0]; int tempLength = 1; // the length is used for the offset, and there is a * for deleted as the first byte DbaseFieldDescriptor[] tempFieldDescriptors = new DbaseFieldDescriptor[_fieldDescriptions.Length + 1]; for (int i = 0; i < _fieldDescriptions.Length; i++) { _fieldDescriptions[i].DataAddress = tempLength; tempLength = tempLength + _fieldDescriptions[i].Length; tempFieldDescriptors[i] = _fieldDescriptions[i]; } tempFieldDescriptors[_fieldDescriptions.Length] = new DbaseFieldDescriptor(); tempFieldDescriptors[_fieldDescriptions.Length].Length = fieldLength; tempFieldDescriptors[_fieldDescriptions.Length].DecimalCount = decimalCount; tempFieldDescriptors[_fieldDescriptions.Length].DataAddress = tempLength; // set the field name string tempFieldName = fieldName; if (tempFieldName == null) tempFieldName = "NoName"; if (tempFieldName.Length > FieldNameMaxLength) { string s = String.Format("FieldName {0} is longer than {1} characters", fieldName, FieldNameMaxLength); throw new ArgumentException(s); } tempFieldDescriptors[_fieldDescriptions.Length].Name = tempFieldName; // the field type if ((fieldType == 'C') || (fieldType == 'c')) { tempFieldDescriptors[_fieldDescriptions.Length].DbaseType = 'C'; if (fieldLength > 254) Trace.WriteLine("Field Length for " + fieldName + " set to " + fieldLength + " Which is longer than 254, not consistent with dbase III"); } else if ((fieldType == 'S') || (fieldType == 's')) { tempFieldDescriptors[_fieldDescriptions.Length].DbaseType = 'C'; Trace.WriteLine("Field type for " + fieldName + " set to S which is flat out wrong people!, I am setting this to C, in the hopes you meant character."); if (fieldLength > 254) Trace.WriteLine("Field Length for " + fieldName + " set to " + fieldLength + " Which is longer than 254, not consistent with dbase III"); tempFieldDescriptors[_fieldDescriptions.Length].Length = 8; } else if ((fieldType == 'D') || (fieldType == 'd')) { tempFieldDescriptors[_fieldDescriptions.Length].DbaseType = 'D'; if (fieldLength != 8) Trace.WriteLine("Field Length for " + fieldName + " set to " + fieldLength + " Setting to 8 digets YYYYMMDD"); tempFieldDescriptors[_fieldDescriptions.Length].Length = 8; } else if ((fieldType == 'F') || (fieldType == 'f')) { tempFieldDescriptors[_fieldDescriptions.Length].DbaseType = 'F'; if (fieldLength > 20) Trace.WriteLine("Field Length for " + fieldName + " set to " + fieldLength + " Preserving length, but should be set to Max of 20 not valid for dbase IV, and UP specification, not present in dbaseIII."); } else if ((fieldType == 'N') || (fieldType == 'n')) { tempFieldDescriptors[_fieldDescriptions.Length].DbaseType = 'N'; if (fieldLength > 18) Trace.WriteLine("Field Length for " + fieldName + " set to " + fieldLength + " Preserving length, but should be set to Max of 18 for dbase III specification."); if (decimalCount < 0) { Trace.WriteLine("Field Decimal Position for " + fieldName + " set to " + decimalCount + " Setting to 0 no decimal data will be saved."); tempFieldDescriptors[_fieldDescriptions.Length].DecimalCount = 0; } if (decimalCount > fieldLength - 1) { Trace.WriteLine("Field Decimal Position for " + fieldName + " set to " + decimalCount + " Setting to " + (fieldLength - 1) + " no non decimal data will be saved."); tempFieldDescriptors[_fieldDescriptions.Length].DecimalCount = fieldLength - 1; } } else if ((fieldType == 'L') || (fieldType == 'l')) { tempFieldDescriptors[_fieldDescriptions.Length].DbaseType = 'L'; if (fieldLength != 1) Trace.WriteLine("Field Length for " + fieldName + " set to " + fieldLength + " Setting to length of 1 for logical fields."); tempFieldDescriptors[_fieldDescriptions.Length].Length = 1; } else { throw new NotSupportedException("Unsupported field type " + fieldType + " For column " + fieldName); } // the length of a record tempLength = tempLength + tempFieldDescriptors[_fieldDescriptions.Length].Length; // set the new fields. _fieldDescriptions = tempFieldDescriptors; _headerLength = 33 + 32 * _fieldDescriptions.Length; _numFields = _fieldDescriptions.Length; _recordLength = tempLength; }
/// <summary> /// Remove a column from this DbaseFileHeader. /// </summary> /// <param name="fieldName"></param> /// <returns>return index of the removed column, -1 if no found.</returns> public int RemoveColumn(string fieldName) { int retCol = -1; int tempLength = 1; DbaseFieldDescriptor[] tempFieldDescriptors = new DbaseFieldDescriptor[_fieldDescriptions.Length - 1]; for (int i = 0, j = 0; i < _fieldDescriptions.Length; i++) { if (fieldName.ToLower() != (_fieldDescriptions[i].Name.Trim().ToLower())) { // if this is the last field and we still haven't found the // named field if (i == j && i == _fieldDescriptions.Length - 1) return retCol; tempFieldDescriptors[j] = _fieldDescriptions[i]; tempFieldDescriptors[j].DataAddress = tempLength; tempLength += tempFieldDescriptors[j].Length; // only increment j on non-matching fields j++; } else retCol = i; } // set the new fields. _fieldDescriptions = tempFieldDescriptors; _headerLength = 33 + 32 * _fieldDescriptions.Length; _numFields = _fieldDescriptions.Length; _recordLength = tempLength; return retCol; }
/// <summary> /// Add a column to this DbaseFileHeader. /// </summary> /// <param name="fieldName">The name of the field to add.</param> /// <param name="fieldType">The type is one of (C N L or D) character, number, logical(true/false), or date.</param> /// <param name="fieldLength"> The Field length is the total length in bytes reserved for this column.</param> /// <param name="decimalCount">The decimal count only applies to numbers(N), and floating point values (F), and refers to the number of characters to reserve after the decimal point.</param> public void AddColumn(string fieldName, char fieldType, int fieldLength, int decimalCount) { if (fieldLength <= 0) { fieldLength = 1; } if (_fieldDescriptions == null) { _fieldDescriptions = new DbaseFieldDescriptor[0]; } int tempLength = 1; // the length is used for the offset, and there is a * for deleted as the first byte DbaseFieldDescriptor[] tempFieldDescriptors = new DbaseFieldDescriptor[_fieldDescriptions.Length + 1]; for (int i = 0; i < _fieldDescriptions.Length; i++) { _fieldDescriptions[i].DataAddress = tempLength; tempLength = tempLength + _fieldDescriptions[i].Length; tempFieldDescriptors[i] = _fieldDescriptions[i]; } tempFieldDescriptors[_fieldDescriptions.Length] = new DbaseFieldDescriptor(); tempFieldDescriptors[_fieldDescriptions.Length].Length = fieldLength; tempFieldDescriptors[_fieldDescriptions.Length].DecimalCount = decimalCount; tempFieldDescriptors[_fieldDescriptions.Length].DataAddress = tempLength; // set the field name string tempFieldName = fieldName; if (tempFieldName == null) { tempFieldName = "NoName"; } if (tempFieldName.Length > 11) { tempFieldName = tempFieldName.Substring(0, 11); Trace.WriteLine("FieldName " + fieldName + " is longer than 11 characters, truncating to " + tempFieldName); } tempFieldDescriptors[_fieldDescriptions.Length].Name = tempFieldName; // the field type if ((fieldType == 'C') || (fieldType == 'c')) { tempFieldDescriptors[_fieldDescriptions.Length].DbaseType = 'C'; if (fieldLength > 254) { Trace.WriteLine("Field Length for " + fieldName + " set to " + fieldLength + " Which is longer than 254, not consistent with dbase III"); } } else if ((fieldType == 'S') || (fieldType == 's')) { tempFieldDescriptors[_fieldDescriptions.Length].DbaseType = 'C'; Trace.WriteLine("Field type for " + fieldName + " set to S which is flat out wrong people!, I am setting this to C, in the hopes you meant character."); if (fieldLength > 254) { Trace.WriteLine("Field Length for " + fieldName + " set to " + fieldLength + " Which is longer than 254, not consistent with dbase III"); } tempFieldDescriptors[_fieldDescriptions.Length].Length = 8; } else if ((fieldType == 'D') || (fieldType == 'd')) { tempFieldDescriptors[_fieldDescriptions.Length].DbaseType = 'D'; if (fieldLength != 8) { Trace.WriteLine("Field Length for " + fieldName + " set to " + fieldLength + " Setting to 8 digets YYYYMMDD"); } tempFieldDescriptors[_fieldDescriptions.Length].Length = 8; } else if ((fieldType == 'F') || (fieldType == 'f')) { tempFieldDescriptors[_fieldDescriptions.Length].DbaseType = 'F'; if (fieldLength > 20) { Trace.WriteLine("Field Length for " + fieldName + " set to " + fieldLength + " Preserving length, but should be set to Max of 20 not valid for dbase IV, and UP specification, not present in dbaseIII."); } } else if ((fieldType == 'N') || (fieldType == 'n')) { tempFieldDescriptors[_fieldDescriptions.Length].DbaseType = 'N'; if (fieldLength > 18) { Trace.WriteLine("Field Length for " + fieldName + " set to " + fieldLength + " Preserving length, but should be set to Max of 18 for dbase III specification."); } if (decimalCount < 0) { Trace.WriteLine("Field Decimal Position for " + fieldName + " set to " + decimalCount + " Setting to 0 no decimal data will be saved."); tempFieldDescriptors[_fieldDescriptions.Length].DecimalCount = 0; } if (decimalCount > fieldLength - 1) { Trace.WriteLine("Field Decimal Position for " + fieldName + " set to " + decimalCount + " Setting to " + (fieldLength - 1) + " no non decimal data will be saved."); tempFieldDescriptors[_fieldDescriptions.Length].DecimalCount = fieldLength - 1; } } else if ((fieldType == 'L') || (fieldType == 'l')) { tempFieldDescriptors[_fieldDescriptions.Length].DbaseType = 'L'; if (fieldLength != 1) { Trace.WriteLine("Field Length for " + fieldName + " set to " + fieldLength + " Setting to length of 1 for logical fields."); } tempFieldDescriptors[_fieldDescriptions.Length].Length = 1; } else { throw new NotSupportedException("Unsupported field type " + fieldType + " For column " + fieldName); } // the length of a record tempLength = tempLength + tempFieldDescriptors[_fieldDescriptions.Length].Length; // set the new fields. _fieldDescriptions = tempFieldDescriptors; _headerLength = 33 + 32 * _fieldDescriptions.Length; _numFields = _fieldDescriptions.Length; _recordLength = tempLength; }