public static Game FromFile(string filepath) { using (FileStream fs = new FileStream(filepath, FileMode.Open)) { string hash = fs.ReadString(); string owner = fs.ReadString(); string repo = fs.ReadString(); string token = fs.ReadString(); byte set = (byte)fs.ReadInt32(); Game game = new Game(filepath, token, owner, repo, hash); game.users = new User[fs.ReadInt32()]; for (int i = 0; i < game.users.Length; i++) game.users[i] = User.FromStream(fs); game.contributors = new string[fs.ReadInt32()]; for (int i = 0; i < game.contributors.Length; i++) game.contributors[i] = fs.ReadString(); game.rowCount = fs.ReadInt32(); game.commits = new CommitCollection(game); game.tableStart = fs.Position; game.rowSize = 40 + game.users.Length; for (game.tableIndex = 0; game.tableIndex < game.rowCount; game.tableIndex++) { fs.Seek(40, SeekOrigin.Current); bool stop = false; for (int i = 0; i < game.users.Length; i++) if (fs.ReadByte() == 0) { stop = true; fs.Seek(-(40 + i + 1), SeekOrigin.Current); break; } if (stop) break; } fs.Seek(game.tableStart + game.rowCount * game.rowSize, SeekOrigin.Begin); while (fs.Position < fs.Length) game.messages.Add(Message.FromStream(fs)); return game; } }
ReplayMetadata(FileStream fs, string path) { FilePath = path; // Read start marker if (fs.ReadInt32() != MetaStartMarker) throw new InvalidOperationException("Expected MetaStartMarker but found an invalid value."); // Read version var version = fs.ReadInt32(); if (version != MetaVersion) throw new NotSupportedException("Metadata version {0} is not supported".F(version)); // Read game info (max 100K limit as a safeguard against corrupted files) var data = fs.ReadString(Encoding.UTF8, 1024 * 100); GameInfo = GameInformation.Deserialize(data); }
/// <summary> /// Reads all log messages from the supplied file. /// </summary> public static List<LogMessage> Read(string logFileName) { List<LogMessage> lst = new List<LogMessage>(); FilePath.ValidatePathName(logFileName); using (var stream = new FileStream(logFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)) { try { LogMessageSaveHelper helper; int version = stream.ReadInt32(); switch (version) { case 282497: helper = LogMessageSaveHelper.Create(); //VersionNumber: Compressed. With LogSaveHelper break; default: throw new VersionNotFoundException(); } using (var zipStream = new DeflateStream(stream, CompressionMode.Decompress, true)) using (var bs = new BufferedStream(zipStream)) { while (bs.ReadBoolean()) { var message = new LogMessage(bs, helper); lst.Add(message); } bs.Dispose(); } } catch (EndOfStreamException) { } catch (ZlibException) { } } return lst; }
/// <summary> /// Reads the entire index file in order to get a breakdown of how shapes are broken up. /// </summary> /// <param name="fileName">A string fileName of the .shx file to read.</param> /// <returns>A List of ShapeHeaders that give offsets and lengths so that reading can be optimized</returns> private List<ShapeHeader> ReadIndexFile(string fileName) { var shxFilename = Path.ChangeExtension(fileName, ".shx"); if (shxFilename == null || !File.Exists(shxFilename) || new FileInfo(shxFilename).Length == 100) { return Enumerable.Empty<ShapeHeader>().ToList(); } // Use a the length of the file to dimension the byte array var fileLen = new FileInfo(shxFilename).Length; using (var bbReader = new FileStream(shxFilename, FileMode.Open)) { // Skip the header and begin reading from the first record bbReader.Seek(100, SeekOrigin.Begin); _header.ShxLength = (int)(fileLen / 2); var length = (int)(fileLen - 100); var numRecords = length / 8; // Each record consists of 2 Big-endian integers for a total of 8 bytes. // This will store the header elements that we read from the file. var result = new List<ShapeHeader>(numRecords); for (var i = 0; i < numRecords; i++) { result.Add(new ShapeHeader { Offset = bbReader.ReadInt32(Endian.BigEndian), ContentLength = bbReader.ReadInt32(Endian.BigEndian), }); } return result; } }
/// <inheritdocs/> protected override Shape GetShapeAtIndex(FileStream fs, ShapefileIndexFile shx, ShapefileHeader header, int shp, IEnvelope envelope) { // Read from the index file because some deleted records // might still exist in the .shp file. long offset = (shx.Shapes[shp].ByteOffset); fs.Seek(offset, SeekOrigin.Begin); Shape myShape = new Shape(); // Position Value Type Number Byte Order ShapeRange shape = new ShapeRange(FeatureType.Line); //-------------------------------------------------------------------- shape.RecordNumber = fs.ReadInt32(Endian.BigEndian); // Byte 0 Record Number Integer 1 Big shape.ContentLength = fs.ReadInt32(Endian.BigEndian); // Byte 4 Content Length Integer 1 Big shape.ShapeType = (ShapeType)fs.ReadInt32(); // Byte 8 Shape Type Integer 1 Little shape.StartIndex = 0; if (shape.ShapeType == ShapeType.NullShape) { return null; } myShape.Range = shape; //bbReader.Read(allBounds, shp*32, 32); double xMin = fs.ReadDouble(); // Byte 12 Xmin Double 1 Little double yMin = fs.ReadDouble(); // Byte 20 Ymin Double 1 Little double xMax = fs.ReadDouble(); // Byte 28 Xmax Double 1 Little double yMax = fs.ReadDouble(); // Byte 36 Ymax Double 1 Little shape.Extent = new Extent(xMin, yMin, xMax, yMax); // Don't add this shape to the result if (envelope != null) { if (!myShape.Range.Extent.Intersects(envelope)) { return null; } } shape.NumParts = fs.ReadInt32(); // Byte 44 NumParts Integer 1 Little //feature.NumPoints = bbReader.ReadInt32(); // Byte 48 NumPoints Integer 1 Little shape.NumPoints = fs.ReadInt32(); // Create an envelope from the extents box in the file. //feature.Envelope = new Envelope(xMin, xMax, yMin, yMax); int[] partIndices = fs.ReadInt32(shape.NumParts); myShape.Vertices = fs.ReadDouble(shape.NumPoints * 2); if (header.ShapeType == ShapeType.PolyLineM) { // These are listed as "optional" but there isn't a good indicator of how to determine if they were added. // To handle the "optional" M values, check the contentLength for the feature. // The content length does not include the 8-byte record header and is listed in 16-bit words. if (shape.ContentLength * 2 > 44 + 4 * shape.NumParts + 16 * shape.NumPoints) { myShape.MinM = fs.ReadDouble(); myShape.MaxM = fs.ReadDouble(); myShape.M = fs.ReadDouble(shape.NumPoints); shape.Extent = new ExtentM(shape.Extent, myShape.MinM, myShape.MaxM); } } else if (header.ShapeType == ShapeType.PolyLineZ) { bool hasM = shape.ContentLength * 2 > 60 + 4 * shape.NumParts + 24 * shape.NumPoints; myShape.MinZ = fs.ReadDouble(); myShape.MaxZ = fs.ReadDouble(); // For Z shapefiles, the Z part is not optional. myShape.Z = fs.ReadDouble(shape.NumPoints); // These are listed as "optional" but there isn't a good indicator of how to determine if they were added. // To handle the "optional" M values, check the contentLength for the feature. // The content length does not include the 8-byte record header and is listed in 16-bit words.) if (hasM) { myShape.MinM = fs.ReadDouble(); myShape.MaxM = fs.ReadDouble(); myShape.M = fs.ReadDouble(shape.NumPoints); shape.Extent = new ExtentMZ(shape.Extent.MinX, shape.Extent.MinY, myShape.MinM, myShape.MinZ, shape.Extent.MaxX, shape.Extent.MaxY, myShape.MaxM, myShape.MaxZ); } else shape.Extent = new ExtentMZ(shape.Extent.MinX, shape.Extent.MinY, double.MaxValue, myShape.MinZ, shape.Extent.MaxX, shape.Extent.MaxY, double.MinValue, myShape.MaxZ); } myShape.Range = shape; for (int part = 0; part < shape.NumParts; part++) { int partOff = partIndices[part]; int pointCount = shape.NumPoints - partOff; if (part < shape.NumParts - 1) { pointCount = partIndices[part + 1] - partOff; } PartRange partR = new PartRange(myShape.Vertices, 0, partOff, FeatureType.Line) { NumVertices = pointCount }; shape.Parts.Add(partR); } return myShape; }
internal static void FillLines(string fileName, IProgressHandler progressHandler, Shapefile shapefile, FeatureType featureType) { // Check to ensure the fileName is not null if (fileName == null) { throw new NullReferenceException(DataStrings.ArgumentNull_S.Replace("%S", "fileName")); } if (shapefile == null) throw new ArgumentNullException("shapefile"); if (File.Exists(fileName) == false) { throw new FileNotFoundException(DataStrings.FileNotFound_S.Replace("%S", fileName)); } if (featureType != FeatureType.Line && featureType != FeatureType.Polygon) { throw new NotSupportedException(); } var header = shapefile.Header; // Check to ensure that the fileName is the correct shape type switch (featureType) { case FeatureType.Line: if (header.ShapeType != ShapeType.PolyLine && header.ShapeType != ShapeType.PolyLineM && header.ShapeType != ShapeType.PolyLineZ) { throw new ArgumentException(DataStrings.FileNotLines_S.Replace("%S", fileName)); } break; case FeatureType.Polygon: if (header.ShapeType != ShapeType.Polygon && header.ShapeType != ShapeType.PolygonM && header.ShapeType != ShapeType.PolygonZ) { throw new ArgumentException(DataStrings.FileNotLines_S.Replace("%S", fileName)); } break; } if (new FileInfo(fileName).Length == 100) { // the file is empty so we are done reading return; } // Reading the headers gives us an easier way to track the number of shapes and their overall length etc. var shapeHeaders = shapefile.ReadIndexFile(fileName); int numShapes = shapeHeaders.Count; bool isM = false, isZ = false; switch (header.ShapeType) { case ShapeType.PolyLineM: case ShapeType.PolygonM: isM = true; break; case ShapeType.PolyLineZ: case ShapeType.PolygonZ: isZ = true; isM = true; break; } int totalPointsCount = 0; int totalPartsCount = 0; var shapeIndices = new List<ShapeRange>(numShapes); var progressMeter = new ProgressMeter(progressHandler, "Reading from " + Path.GetFileName(fileName)) { StepPercent = 5 }; using (var reader = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, 65536)) { var boundsBytes = new byte[4 * 8]; var bounds = new double[4]; for (int shp = 0; shp < numShapes; shp++) { progressMeter.CurrentPercent = (int)(shp * 50.0 / numShapes); // Read from the index file because some deleted records // might still exist in the .shp file. long offset = (shapeHeaders[shp].ByteOffset); reader.Seek(offset, SeekOrigin.Begin); var shape = new ShapeRange(featureType, shapefile.CoordinateType) { RecordNumber = reader.ReadInt32(Endian.BigEndian), ContentLength = reader.ReadInt32(Endian.BigEndian), ShapeType = (ShapeType)reader.ReadInt32(), StartIndex = totalPointsCount }; Debug.Assert(shape.RecordNumber == shp + 1); if (shape.ShapeType != ShapeType.NullShape) { // Bounds reader.Read(boundsBytes, 0, boundsBytes.Length); Buffer.BlockCopy(boundsBytes, 0, bounds, 0, boundsBytes.Length); shape.Extent.MinX = bounds[0]; shape.Extent.MinY = bounds[1]; shape.Extent.MaxX = bounds[2]; shape.Extent.MaxY = bounds[3]; // Num Parts shape.NumParts = reader.ReadInt32(); totalPartsCount += shape.NumParts; // Num Points shape.NumPoints = reader.ReadInt32(); totalPointsCount += shape.NumPoints; } shapeIndices.Add(shape); } var vert = new double[totalPointsCount * 2]; var vertInd = 0; var parts = new int[totalPartsCount]; var partsInd = 0; double[] mArray = null, zArray = null; if (isM) { mArray = new double[totalPointsCount]; } int mArrayInd = 0; if (isZ) { zArray = new double[totalPointsCount]; } int zArrayInd = 0; int partsOffset = 0; for (int shp = 0; shp < numShapes; shp++) { progressMeter.CurrentPercent = (int)(50 + shp * 50.0 / numShapes); var shape = shapeIndices[shp]; if (shape.ShapeType == ShapeType.NullShape) continue; reader.Seek(shapeHeaders[shp].ByteOffset, SeekOrigin.Begin); reader.Seek(3 * 4 + 32 + 2 * 4, SeekOrigin.Current); // Skip first bytes // Read parts var partsBytes = reader.ReadBytes(4 * shape.NumParts); Buffer.BlockCopy(partsBytes, 0, parts, partsInd, partsBytes.Length); partsInd += 4 * shape.NumParts; // Read points var pointsBytes = reader.ReadBytes(8 * 2 * shape.NumPoints); Buffer.BlockCopy(pointsBytes, 0, vert, vertInd, pointsBytes.Length); vertInd += 8 * 2 * shape.NumPoints; // Fill parts shape.Parts.Capacity = shape.NumParts; for (int part = 0; part < shape.NumParts; part++) { int endIndex = shape.NumPoints + shape.StartIndex; int startIndex = parts[partsOffset + part] + shape.StartIndex; if (part < shape.NumParts - 1) { endIndex = parts[partsOffset + part + 1] + shape.StartIndex; } int count = endIndex - startIndex; var partR = new PartRange(vert, shape.StartIndex, parts[partsOffset + part], featureType) { NumVertices = count }; shape.Parts.Add(partR); } partsOffset += shape.NumParts; // Fill M and Z arrays switch (header.ShapeType) { case ShapeType.PolyLineM: case ShapeType.PolygonM: if (shape.ContentLength * 2 > 44 + 4 * shape.NumParts + 16 * shape.NumPoints) { var mExt = (IExtentM)shape.Extent; mExt.MinM = reader.ReadDouble(); mExt.MaxM = reader.ReadDouble(); var mBytes = reader.ReadBytes(8 * shape.NumPoints); Buffer.BlockCopy(mBytes, 0, mArray, mArrayInd, mBytes.Length); mArrayInd += 8 * shape.NumPoints; } break; case ShapeType.PolyLineZ: case ShapeType.PolygonZ: var zExt = (IExtentZ)shape.Extent; zExt.MinZ = reader.ReadDouble(); zExt.MaxZ = reader.ReadDouble(); var zBytes = reader.ReadBytes(8 * shape.NumPoints); Buffer.BlockCopy(zBytes, 0, zArray, zArrayInd, zBytes.Length); zArrayInd += 8 * shape.NumPoints; // These are listed as "optional" but there isn't a good indicator of how to // determine if they were added. // To handle the "optional" M values, check the contentLength for the feature. // The content length does not include the 8-byte record header and is listed in 16-bit words. if (shape.ContentLength * 2 > 60 + 4 * shape.NumParts + 24 * shape.NumPoints) { goto case ShapeType.PolyLineM; } break; } } if (isM) shapefile.M = mArray; if (isZ) shapefile.Z = zArray; shapefile.ShapeIndices = shapeIndices; shapefile.Vertex = vert; } progressMeter.Reset(); }
static ReplayMetadata Read(FileStream fs, string path) { if (!fs.CanSeek) return null; if (fs.Length < 20) return null; try { fs.Seek(-(4 + 4), SeekOrigin.End); var dataLength = fs.ReadInt32(); if (fs.ReadInt32() == MetaEndMarker) { // go back by (end marker + length storage + data + version + start marker) bytes fs.Seek(-(4 + 4 + dataLength + 4 + 4), SeekOrigin.Current); try { return new ReplayMetadata(fs, path); } catch (YamlException ex) { Log.Write("debug", ex.ToString()); } catch (InvalidOperationException ex) { Log.Write("debug", ex.ToString()); } catch (NotSupportedException ex) { Log.Write("debug", ex.ToString()); } } } catch (IOException ex) { Log.Write("debug", ex.ToString()); } return null; }
/// <summary> /// Reads the entire index file in order to get a breakdown of how shapes are broken up. /// </summary> /// <param name="fileName">A string fileName of the .shx file to read.</param> /// <returns>A List of ShapeHeaders that give offsets and lengths so that reading can be optimized</returns> public List<ShapeHeader> ReadIndexFile(string fileName) { string shxFilename = fileName; string ext = Path.GetExtension(fileName); if (ext != ".shx") { shxFilename = Path.ChangeExtension(fileName, ".shx"); } if (shxFilename == null) { throw new NullReferenceException(DataStrings.ArgumentNull_S.Replace("%S", fileName)); } if (File.Exists(shxFilename) == false) { throw new FileNotFoundException(DataStrings.FileNotFound_S.Replace("%S", fileName)); } var fileLen = new FileInfo(shxFilename).Length; if (fileLen == 100) { // the file is empty so we are done reading return Enumerable.Empty<ShapeHeader>().ToList(); } // Use a the length of the file to dimension the byte array using (var bbReader = new FileStream(shxFilename, FileMode.Open, FileAccess.Read, FileShare.Read, 65536)) { // Skip the header and begin reading from the first record bbReader.Seek(100, SeekOrigin.Begin); _header.ShxLength = (int)(fileLen / 2); var length = (int)(fileLen - 100); var numRecords = length / 8; // Each record consists of 2 Big-endian integers for a total of 8 bytes. // This will store the header elements that we read from the file. var result = new List<ShapeHeader>(numRecords); for (var i = 0; i < numRecords; i++) { result.Add(new ShapeHeader { Offset = bbReader.ReadInt32(Endian.BigEndian), ContentLength = bbReader.ReadInt32(Endian.BigEndian), }); } return result; } }
/// <summary> /// Obtains a typed list of ShapefilePoint structures with double values associated with the various coordinates. /// </summary> /// <param name="fileName">A string fileName</param> private void FillPoints(string fileName) { // Check to ensure the fileName is not null if (fileName == null) { throw new NullReferenceException(DataStrings.ArgumentNull_S.Replace("%S", fileName)); } if (File.Exists(fileName) == false) { throw new FileNotFoundException(DataStrings.FileNotFound_S.Replace("%S", fileName)); } // Reading the headers gives us an easier way to track the number of shapes and their overall length etc. List<ShapeHeader> shapeHeaders = ReadIndexFile(fileName); // Get the basic header information. ShapefileHeader header = new ShapefileHeader(fileName); Extent = header.ToExtent(); // Check to ensure that the fileName is the correct shape type if (header.ShapeType != ShapeType.Point && header.ShapeType != ShapeType.PointM && header.ShapeType != ShapeType.PointZ) { throw new ApplicationException(DataStrings.FileNotPoints_S.Replace("%S", fileName)); } if (new FileInfo(fileName).Length == 100) { // the file is empty so we are done reading return; } var numShapes = shapeHeaders.Count; double[] m = null; double[] z = null; var vert = new double[2 * numShapes]; // X,Y if (header.ShapeType == ShapeType.PointM || header.ShapeType == ShapeType.PointZ) { m = new double[numShapes]; } if (header.ShapeType == ShapeType.PointZ) { z = new double[numShapes]; } using (var reader = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { for (var shp = 0; shp < numShapes; shp++) { reader.Seek(shapeHeaders[shp].ByteOffset, SeekOrigin.Begin); var recordNumber = reader.ReadInt32(Endian.BigEndian); Debug.Assert(recordNumber == shp + 1); var contentLen = reader.ReadInt32(Endian.BigEndian); Debug.Assert(contentLen == shapeHeaders[shp].ContentLength); var shapeType = (ShapeType) reader.ReadInt32(Endian.LittleEndian); if (shapeType == ShapeType.NullShape) { if (m != null) { m[shp] = double.MinValue; } goto fin; } // Read X var ind = 4; vert[shp*2] = reader.ReadDouble(1, Endian.LittleEndian)[0]; ind += 8; // Read Y vert[shp*2 + 1] = reader.ReadDouble(1, Endian.LittleEndian)[0]; ind += 8; // Read Z if (z != null) { z[shp] = reader.ReadDouble(1, Endian.LittleEndian)[0]; ind += 8; } // Read M if (m != null) { if (shapeHeaders[shp].ByteLength <= ind) { m[shp] = double.MinValue; } else { m[shp] = reader.ReadDouble(1, Endian.LittleEndian)[0]; ind += 8; } } fin: var shape = new ShapeRange(FeatureType.Point) { StartIndex = shp, ContentLength = shapeHeaders[shp].ContentLength, NumPoints = 1, NumParts = 1 }; ShapeIndices.Add(shape); var part = new PartRange(vert, shp, 0, FeatureType.Point) {NumVertices = 1}; shape.Parts.Add(part); shape.Extent = new Extent(new[] {vert[shp*2], vert[shp*2 + 1], vert[shp*2], vert[shp*2 + 1]}); } } Vertex = vert; M = m; Z = z; }
/// <inheritdocs/> protected override Shape GetShapeAtIndex(FileStream fs, ShapefileIndexFile shx, ShapefileHeader header, int shp, IEnvelope envelope) { // Read from the index file because some deleted records // might still exist in the .shp file. long offset = (shx.Shapes[shp].ByteOffset); fs.Seek(offset, SeekOrigin.Begin); Shape myShape = new Shape(); // Position Value Type Number Byte Order ShapeRange shape = new ShapeRange(FeatureType.Point); //-------------------------------------------------------------------- shape.RecordNumber = fs.ReadInt32(Endian.BigEndian); // Byte 0 Record Number Integer 1 Big shape.ContentLength = fs.ReadInt32(Endian.BigEndian); // Byte 4 Content Length Integer 1 Big ShapeType shapeType = (ShapeType)fs.ReadInt32(); // Byte 8 Shape Type Integer 1 Little if (shapeType == ShapeType.NullShape) { return null; } double[] vertices = fs.ReadDouble(2); double x = vertices[0], y = vertices[1]; // Don't add this shape to the result if (envelope != null) { if (!envelope.Contains(new Coordinate(x, y))) { return null; } } shape.StartIndex = 0; shape.NumParts = 1; shape.NumPoints = 1; shape.ShapeType = shapeType; shape.Extent = new Extent(x, y, x, y); myShape.Range = shape; myShape.Vertices = vertices; if (header.ShapeType == ShapeType.PointM) { myShape.M = fs.ReadDouble(1); myShape.MinM = myShape.MaxM = myShape.M[0]; shape.Extent = new ExtentM(shape.Extent, myShape.MinM, myShape.MaxM); } else if (header.ShapeType == ShapeType.PointZ) { // For Z shapefiles, the Z part is not optional. myShape.Z = fs.ReadDouble(1); myShape.MinZ = myShape.MaxZ = myShape.Z[0]; myShape.M = fs.ReadDouble(1); myShape.MinM = myShape.MaxM = myShape.M[0]; shape.Extent = new ExtentMZ(shape.Extent.MinX, shape.Extent.MinY, myShape.MinM, myShape.MinZ, shape.Extent.MaxX, shape.Extent.MaxY, myShape.MaxM, myShape.MaxZ); } PartRange partR = new PartRange(myShape.Vertices, 0, 0, FeatureType.Point) { NumVertices = 1 }; shape.Parts.Add(partR); myShape.Range = shape; return myShape; }
/// <summary> /// Parses the first 100 bytes of a shapefile into the important values /// </summary> /// <param name="inFilename">The fileName to read</param> public void Open(string inFilename) { Filename = inFilename; // Position Field Value Type ByteOrder // -------------------------------------------------------------- // Byte 0 File Code 9994 Integer Big // Byte 4 Unused 0 Integer Big // Byte 8 Unused 0 Integer Big // Byte 12 Unused 0 Integer Big // Byte 16 Unused 0 Integer Big // Byte 20 Unused 0 Integer Big // Byte 24 File Length File Length Integer Big // Byte 28 Version 1000 Integer Little // Byte 32 Shape Type Shape Type Integer Little // Byte 36 Bounding Box Xmin Double Little // Byte 44 Bounding Box Ymin Double Little // Byte 52 Bounding Box Xmax Double Little // Byte 60 Bounding Box Ymax Double Little // Byte 68 Bounding Box Zmin Double Little // Byte 76 Bounding Box Zmax Double Little // Byte 84 Bounding Box Mmin Double Little // Byte 92 Bounding Box Mmax Double Little // This may throw an IOException if the file is already in use. using (var bbReader = new FileStream(inFilename, FileMode.Open)) { // Reading BigEndian simply requires us to reverse the byte order. FileCode = bbReader.ReadInt32(Endian.BigEndian); // Skip the next 20 bytes because they are unused bbReader.Seek(20, SeekOrigin.Current); // Read the file length in reverse sequence FileLength = bbReader.ReadInt32(Endian.BigEndian); // From this point on, all the header values are in little Endean // Read the version Version = bbReader.ReadInt32(); // Read in the shape type that should be the shape type for the whole shapefile ShapeType = (ShapeType) bbReader.ReadInt32(); // Get the extents, each of which are double values. Xmin = bbReader.ReadDouble(); Ymin = bbReader.ReadDouble(); Xmax = bbReader.ReadDouble(); Ymax = bbReader.ReadDouble(); Zmin = bbReader.ReadDouble(); Zmax = bbReader.ReadDouble(); Mmin = bbReader.ReadDouble(); Mmax = bbReader.ReadDouble(); } var fi = new FileInfo(ShxFilename); if (fi.Exists) { ShxLength = Convert.ToInt32(fi.Length / 2); //length is in 16 bit words. } }