public static ShapeInfo GetShapeInfo(string p_SourceDir, string p_FileName)
        {
            ShapeInfo RetVal = null;

            //-- Check for shape file set existence
            if (File.Exists(p_SourceDir + "\\" + p_FileName + ".shp") && File.Exists(p_SourceDir + "\\" + p_FileName + ".shx") && File.Exists(p_SourceDir + "\\" + p_FileName + ".dbf"))
            {

                FileHeader SHPFileHeader = new FileHeader();
                SHPRecordHeader SHPRecordHeader = new SHPRecordHeader();
                FileStream objSHPStream = null;
                BinaryReader objSHPBinaryReader = null;

                FileHeader SHXFileHeader = new FileHeader();
                SHXRecordHeader SHXRecordHeader = new SHXRecordHeader();
                FileStream objSHXStream = null;
                BinaryReader objSHXBinaryReader = null;

                FileStream dbfStream = null;
                BinaryReader dbfReader = null;
                System.Text.Encoding FileEncoding;      // To hold encoding type on the basis of code Page value defined in .dbf header.

                int i;
                int j;
                int k;
                try
                {
                    objSHPStream = File.OpenRead(p_SourceDir + "\\" + p_FileName + ".shp");
                    objSHPBinaryReader = new BinaryReader(objSHPStream);
                    objSHXStream = File.OpenRead(p_SourceDir + "\\" + p_FileName + ".shx");
                    objSHXBinaryReader = new BinaryReader(objSHXStream);

                    //-- get Encoding used to create dbf file. This PageCode information is in 29th position of dbfReader.
                    FileEncoding = ShapeFileReader.GetEncodingInDBF(p_SourceDir + "\\" + p_FileName + ".dbf");
                    dbfStream = File.OpenRead(p_SourceDir + "\\" + p_FileName + ".dbf");
                    //dbfReader = new BinaryReader(dbfStream, System.Text.Encoding.GetEncoding(65001)); // 65001 is the code page for Unicode UTF-8 encoding taken as default'

                    dbfReader = new BinaryReader(dbfStream, FileEncoding);

                    SHPFileHeader = ReadHeaderInfo(ref objSHPBinaryReader);
                    SHXFileHeader = ReadHeaderInfo(ref objSHXBinaryReader);

                    ShapeInfo _ShapeInfo = new ShapeInfo();
                    _ShapeInfo.ID = p_FileName;
                    _ShapeInfo.Extent = new RectangleF((float)SHPFileHeader.BoundingBoxXMin, (float)SHPFileHeader.BoundingBoxYMin, (float)Math.Abs(SHPFileHeader.BoundingBoxXMax - SHPFileHeader.BoundingBoxXMin), (float)Math.Abs(SHPFileHeader.BoundingBoxYMax - SHPFileHeader.BoundingBoxYMin));
                    _ShapeInfo.RecordCount = (int)(SHXFileHeader.FileLength - 50) / 4;

                    _ShapeInfo.ShapeType = (DevInfo.Lib.DI_LibBAL.UI.Presentations.Map.ShapeType)SHPFileHeader.ShapeType;

                    if ((int)(_ShapeInfo.ShapeType) == (int)(ShapeFileReader.ShapeType.PointZ))
                    {
                        _ShapeInfo.ShapeType = DevInfo.Lib.DI_LibBAL.UI.Presentations.Map.ShapeType.Point;
                    }

                    //*** Read dbf header and set Id and Label Field
                    string sFieldId = "";
                    string sFieldLabel = "";

                    byte dbfVersion = dbfReader.ReadByte();
                    //3
                    byte updateYear = dbfReader.ReadByte();
                    byte updateMonth = dbfReader.ReadByte();
                    byte updateDay = dbfReader.ReadByte();

                    Int32 numberRecords = dbfReader.ReadInt32();
                    //
                    short headerLength = dbfReader.ReadInt16();
                    //
                    short recordLength = dbfReader.ReadInt16();
                    //**** In Reserved Bytes, there is a byte (flag) at 29th postion of stream which represent code page information, that can be used to get Encoding type.
                    dbfStream.Seek(29, SeekOrigin.Begin);     // Seek to 29th postion to fetch code page .
                    FileEncoding = GetDbaseEncodingType(dbfReader.ReadByte());   // Reads code page and gets the corresponding encoding type.
                    dbfStream.Seek(32, SeekOrigin.Begin);  // Move to past the reserved bytes.
                    // byte[] reserved = dbfReader.ReadBytes(20);
                    Int32 numberFields = (int)(headerLength - 33) / 32;

                    DBF_Field_Header[] fieldHeaders = new DBF_Field_Header[numberFields];
                    string FieldName;
                    for (i = 0; i <= numberFields - 1; i++)
                    {
                        //byte[] testBytes = FileEncoding.GetBytes(dbfReader.ReadChars(10));
                        ////dbfReader.BaseStream.Position -= 10;
                        //testBytes = System.Text.Encoding.Convert(System.Text.Encoding.UTF8, FileEncoding, testBytes);
                        try
                        {
                            char[] fieldNameChars = dbfReader.ReadChars(10);
                            char fieldNameTerminator = dbfReader.ReadChar();
                            FieldName = new string(fieldNameChars).ToUpper();
                            fieldHeaders[i].FieldName = FieldName;
                            fieldHeaders[i].FieldType = dbfReader.ReadChar();

                            if (FieldName.Length >= 3 && fieldHeaders[i].FieldName.Replace("\0","").Trim() == ID_FIELD_NAME)
                            {
                                if (FieldName[0] == 'I' & FieldName[1] == 'D' & FieldName[2] == '_')
                                    sFieldId = fieldHeaders[i].FieldName;
                            }

                            if (FieldName.Length >= 6 && fieldHeaders[i].FieldName.Replace("\0", "").Trim() == NAME1_FIELD_NAME)
                            {
                                if (FieldName[0] == 'N' & FieldName[1] == 'A' & FieldName[2] == 'M' & FieldName[3] == 'E' & FieldName[4] == '1' & FieldName[5] == '_')
                                    sFieldLabel = fieldHeaders[i].FieldName;
                            }

                            byte[] reserved1 = dbfReader.ReadBytes(4);
                            fieldHeaders[i].FieldLength = dbfReader.ReadByte();
                            byte[] reserved2 = dbfReader.ReadBytes(15);
                        }
                        catch (Exception ex)
                        {
                            Console.Write(ex.Message);
                        }

                    }
                    byte headerTerminator = dbfReader.ReadByte();
                    //13

                    if (sFieldId == "")
                        sFieldId = fieldHeaders[0].FieldName;
                    if (sFieldLabel == "")
                    {
                        if (fieldHeaders.Length > 1)
                        {
                            sFieldLabel = fieldHeaders[1].FieldName;
                        }
                        else
                        {
                            sFieldLabel = fieldHeaders[0].FieldName;
                        }
                    }

                    int numParts;
                    int numPoints;
                    int[] theParts;
                    PointF[] Pt;
                    float Ydiff = 0;
                    //*** Add Ydiff to make all Y coordinates positve for area calculation. if extent of polygon goes below equator
                    //*** Special Handling for centroids of areas lying in 3rd quadrent
                    //*** http://astronomy.swin.edu.au/~pbourke/geometry/polyarea/
                    //*** http://www.geog.ubc.ca/courses/klink/gis.notes/ncgia/u33.html
                    //*** X = S ((y(i) - y(i+1)) (x(i)2 + x(i)x(i+1) + x(i+1)2)/6A) Y = S ((x(i+1) - x(i)) (y(i)2 + y(i)y(i+1) + y(i+1)2)/6A) where A is the area of the polygon
                    //*** note: as with the area algorithm, the polygon must be coded clockwise and all y coordinates must be non- negative

                    for (i = 0; i <= _ShapeInfo.RecordCount - 1; i++)
                    {

                        SHXRecordHeader.Offset = BigToLittleEndian(objSHXBinaryReader.ReadInt32());
                        SHXRecordHeader.ContentLength = BigToLittleEndian(objSHXBinaryReader.ReadInt32());

                        objSHPStream.Seek(SHXRecordHeader.Offset * 2, SeekOrigin.Begin);

                        SHPRecordHeader.RecordNumber = BigToLittleEndian(objSHPBinaryReader.ReadInt32());
                        SHPRecordHeader.ContentLength = BigToLittleEndian(objSHPBinaryReader.ReadInt32());

                        objSHPBinaryReader.ReadInt32();
                        //ShapeType

                        byte isValid = dbfReader.ReadByte();
                        //32

                        Shape _Shape = new Shape();
                        RectangleF _Extent = new RectangleF();

                        {
                            for (j = 0; j <= fieldHeaders.Length - 1; j++)
                            {
                                char[] fieldDataChars;
                                if (fieldHeaders[j].FieldName == sFieldId)
                                {
                                    //Fetch AreaID from .dbf file using default encoding which is set to UTF-8.
                                    fieldDataChars = dbfReader.ReadChars(fieldHeaders[j].FieldLength);
                                    _Shape.AreaId = new string(fieldDataChars).Trim();
                                }
                                else if (fieldHeaders[j].FieldName == sFieldLabel)
                                {
                                    //Fetch the value from "NAME1_" column in its original encoded characters using extracted encoding type.
                                    fieldDataChars = FileEncoding.GetString(dbfReader.ReadBytes(fieldHeaders[j].FieldLength)).Replace("\0", "").Trim().ToCharArray();
                                    _Shape.AreaName = new string(fieldDataChars).Trim();
                                }
                                else
                                {
                                    fieldDataChars = dbfReader.ReadChars(fieldHeaders[j].FieldLength);
                                }
                                //string fieldData = new string(fieldDataChars).Trim(); // unused statement
                            }

                            switch (SHPFileHeader.ShapeType)
                            {
                                case (int)ShapeType.Point:
                                case (int)(ShapeFileReader.ShapeType.PointZ):
                                    PointF _Pt = new PointF();
                                    _Pt.X = (float)objSHPBinaryReader.ReadDouble();
                                    _Pt.Y = (float)objSHPBinaryReader.ReadDouble();
                                    _Shape.Parts.Add(_Pt);
                                    break;
                                case (int)ShapeType.PolyLine:
                                    _Extent.X = (float)objSHPBinaryReader.ReadDouble();
                                    //Byte 04 Minx
                                    _Extent.Y = (float)objSHPBinaryReader.ReadDouble();
                                    //Byte 12 MinY
                                    _Extent.Width = (float)Math.Abs(_Extent.X - objSHPBinaryReader.ReadDouble());
                                    //Byte 20 MaxX
                                    _Extent.Height = (float)Math.Abs(_Extent.Y - objSHPBinaryReader.ReadDouble());
                                    //Byte 28 MaxY
                                    _Shape.Extent = _Extent;

                                    numParts = objSHPBinaryReader.ReadInt32();
                                    //Byte 36 Num Parts
                                    numPoints = objSHPBinaryReader.ReadInt32();
                                    //Byte 40 Num Points

                                    theParts = new int[numParts];
                                    for (j = 0; j <= numParts - 1; j++)
                                    {
                                        theParts[j] = objSHPBinaryReader.ReadInt32();
                                    }

                                    for (j = 0; j <= numParts - 1; j++)
                                    {
                                        if ((j != numParts - 1))
                                        {
                                            Pt = new PointF[theParts[j + 1] - theParts[j]];
                                            for (k = theParts[j]; k <= theParts[j + 1] - 1; k++)
                                            {
                                                Pt[k - theParts[j]].X = (float)objSHPBinaryReader.ReadDouble();
                                                Pt[k - theParts[j]].Y = (float)objSHPBinaryReader.ReadDouble();
                                            }
                                        }
                                        else
                                        {
                                            Pt = new PointF[numPoints - theParts[j]];
                                            for (k = theParts[j]; k <= numPoints - 1; k++)
                                            {
                                                Pt[k - theParts[j]].X = (float)objSHPBinaryReader.ReadDouble();
                                                Pt[k - theParts[j]].Y = (float)objSHPBinaryReader.ReadDouble();
                                            }
                                        }
                                        _Shape.Parts.Add(Pt);
                                    }

                                    break;

                                case (int)ShapeType.Polygon:
                                    //*** Bugfix 27 Sep 2006 Centroid calulation for very small polygon 'Mayanmar problem
                                    double second_factor;
                                    //*** For centroid calculation
                                    double[] polygon_area;
                                    //*** SignedPolygonArea
                                    double[] Cx;
                                    double[] Cy;

                                    _Extent.X = (float)objSHPBinaryReader.ReadDouble();
                                    //Byte 04 Minx
                                    _Extent.Y = (float)objSHPBinaryReader.ReadDouble();
                                    //Byte 12 MinY
                                    _Extent.Width = (float)Math.Abs(_Extent.X - objSHPBinaryReader.ReadDouble());
                                    //Byte 20 MaxX
                                    _Extent.Height = (float)Math.Abs(_Extent.Y - objSHPBinaryReader.ReadDouble());
                                    //Byte 28 MaxY
                                    _Shape.Extent = _Extent;

                                    if (_Extent.Y < 0)
                                        Ydiff = -(_Extent.Y);

                                    numParts = objSHPBinaryReader.ReadInt32();
                                    //Byte 36 Num Parts
                                    numPoints = objSHPBinaryReader.ReadInt32();
                                    //Byte 40 Num Points

                                    theParts = new int[numParts];
                                    for (j = 0; j <= numParts - 1; j++)
                                    {
                                        theParts[j] = objSHPBinaryReader.ReadInt32();
                                    }

                                    Cx = new double[numParts];
                                    Cy = new double[numParts];
                                    polygon_area = new double[numParts];

                                    for (j = 0; j <= numParts - 1; j++)
                                    {
                                        if ((j != numParts - 1))
                                        {
                                            Pt = new PointF[theParts[j + 1] - theParts[j]];
                                            for (k = theParts[j]; k <= theParts[j + 1] - 1; k++)
                                            {
                                                Pt[k - theParts[j]].X = (float)objSHPBinaryReader.ReadDouble();
                                                Pt[k - theParts[j]].Y = (float)objSHPBinaryReader.ReadDouble();
                                                if (k > theParts[j])
                                                {
                                                    polygon_area[j] = polygon_area[j] + (Pt[k - theParts[j]].X - Pt[k - theParts[j] - 1].X) * ((Pt[k - theParts[j]].Y + Ydiff) + (Pt[k - theParts[j] - 1].Y + Ydiff)) / 2;
                                                    second_factor = Pt[k - theParts[j] - 1].X * (Pt[k - theParts[j]].Y + Ydiff) - Pt[k - theParts[j]].X * (Pt[k - theParts[j] - 1].Y + Ydiff);
                                                    Cx[j] = Cx[j] + (Pt[k - theParts[j] - 1].X + Pt[k - theParts[j]].X) * second_factor;
                                                    Cy[j] = Cy[j] + ((Pt[k - theParts[j] - 1].Y + Ydiff) + (Pt[k - theParts[j]].Y + Ydiff)) * second_factor;
                                                }
                                            }
                                        }
                                        else
                                        {
                                            Pt = new PointF[numPoints - theParts[j]];
                                            for (k = theParts[j]; k <= numPoints - 1; k++)
                                            {
                                                Pt[k - theParts[j]].X = (float)objSHPBinaryReader.ReadDouble();
                                                Pt[k - theParts[j]].Y = (float)objSHPBinaryReader.ReadDouble();
                                                if (k > theParts[j])
                                                {
                                                    polygon_area[j] = polygon_area[j] + (Pt[k - theParts[j]].X - Pt[k - theParts[j] - 1].X) * ((Pt[k - theParts[j]].Y + Ydiff) + (Pt[k - theParts[j] - 1].Y + Ydiff)) / 2;
                                                    second_factor = Pt[k - theParts[j] - 1].X * (Pt[k - theParts[j]].Y + Ydiff) - Pt[k - theParts[j]].X * (Pt[k - theParts[j] - 1].Y + Ydiff);
                                                    Cx[j] = Cx[j] + (Pt[k - theParts[j] - 1].X + Pt[k - theParts[j]].X) * second_factor;
                                                    Cy[j] = Cy[j] + ((Pt[k - theParts[j] - 1].Y + Ydiff) + (Pt[k - theParts[j]].Y + Ydiff)) * second_factor;
                                                }
                                            }
                                        }
                                        _Shape.Parts.Add(Pt);
                                        if (polygon_area[j] == 0)
                                        {
                                            Cx[j] = 0;
                                            //*** Indonesia problem
                                            Cy[j] = 0;
                                        }
                                        else
                                        {
                                            Cx[j] = Cx[j] / 6 / polygon_area[j];
                                            // Divide by 6 times the polygon's area.
                                            Cy[j] = Cy[j] / 6 / polygon_area[j];
                                        }
                                    }

                                    double SumCx = 0;
                                    double SumCy = 0;
                                    double SumA = 0;
                                    for (j = 0; j <= numParts - 1; j++)
                                    {
                                        SumCx = SumCx + Cx[j] * polygon_area[j];
                                        SumCy = SumCy + Cy[j] * polygon_area[j];
                                        SumA = SumA + polygon_area[j];
                                    }

                                    SumCx = SumCx / SumA;
                                    SumCy = SumCy / SumA;
                                    if (SumCx < 0 | SumCy < 0)
                                    {
                                        //*** If the values are negative, the polygon is oriented counterclockwise. Reverse the signs.
                                        SumCx = -SumCx;
                                        SumCy = -SumCy;
                                    }

                                    _Shape.Centroid = new PointF((float)SumCx, (float)SumCy - Ydiff);
                                    break;
                            }
                            _ShapeInfo.Records.Add(_Shape.AreaId, _Shape);
                            _Shape = null;
                        }
                    }

                    RetVal = _ShapeInfo;
                }
                catch (Exception ex)
                {
                    Console.Write(ex.Message);
                }
                finally
                {
                    //-- Deallocate the memory used for garbage collector to remove the memory utilized
                    objSHPStream.Close();
                    objSHPStream = null;
                    objSHXStream.Close();
                    objSHXStream = null;
                    dbfStream.Close();
                    dbfStream = null;

                    objSHPBinaryReader.Close();
                    objSHPBinaryReader = null;
                    objSHXBinaryReader.Close();
                    objSHXBinaryReader = null;
                    dbfReader.Close();
                    dbfReader = null;
                    // SHPFileHeader = null;
                    // SHXFileHeader = null;
                    // SHXRecordHeader = null;
                    // SHPRecordHeader = null;
                }
            }

            return RetVal;
        }
        public static DataTable GetDbfTable(string dbfPath)
        {
            FileStream dbfStream;
            BinaryReader dbfReader;
            System.Text.Encoding FileEncoding = ShapeFileReader.GetEncodingInDBF(dbfPath);
            dbfStream = File.OpenRead(dbfPath);
            dbfReader = new BinaryReader(dbfStream, FileEncoding);

            int i;
            int j;

            //*** Read dbf header and set Id and Label Field
            string sFieldId = "";
            string sFieldLabel = "";

            byte dbfVersion = dbfReader.ReadByte();
            //3
            byte updateYear = dbfReader.ReadByte();
            byte updateMonth = dbfReader.ReadByte();
            byte updateDay = dbfReader.ReadByte();

            Int32 numberRecords = dbfReader.ReadInt32();
            //
            short headerLength = dbfReader.ReadInt16();
            //
            short recordLength = dbfReader.ReadInt16();
            byte[] reserved = dbfReader.ReadBytes(20);
            Int32 numberFields = (int)(headerLength - 33) / 32;

            DBF_Field_Header[] fieldHeaders = new DBF_Field_Header[numberFields];
            string FieldName;

            DataTable _DT = new DataTable("tblMapArea");

            _DT.Columns.Add("AreaId", Type.GetType("System.String"));
            //MaxLen - 255
            _DT.Columns.Add("AreaName", Type.GetType("System.String"));
            //MaxLen - 60
            //*** validation for max lenght
            _DT.Columns[0].MaxLength = 255;
            _DT.Columns[1].MaxLength = 60;

            for (i = 0; i <= numberFields - 1; i++)
            {
                char[] fieldNameChars = dbfReader.ReadChars(10);
                char fieldNameTerminator = dbfReader.ReadChar();
                FieldName = new string(fieldNameChars).ToUpper();
                fieldHeaders[i].FieldName = FieldName;
                fieldHeaders[i].FieldType = dbfReader.ReadChar();
                //http://www.dbase.com/KnowledgeBase/int/db7_file_fmt.htm
                //BugFix 12 July 2006 ID_ and NAME1_ field may not be the first and second field
                if (FieldName.Length >= 3 && fieldHeaders[i].FieldName.Replace("\0", "").Trim() == ID_FIELD_NAME)
                {
                    if (FieldName[0] == 'I' & FieldName[1] == 'D' & FieldName[2] == '_')
                        sFieldId = fieldHeaders[i].FieldName;
                }
                if (FieldName.Length >= 6 && fieldHeaders[i].FieldName.Replace("\0", "").Trim() == NAME1_FIELD_NAME)
                {
                    if (FieldName[0] == 'N' & FieldName[1] == 'A' & FieldName[2] == 'M' & FieldName[3] == 'E' & FieldName[4] == '1' & FieldName[5] == '_')
                        sFieldLabel = fieldHeaders[i].FieldName;
                }
                byte[] reserved1 = dbfReader.ReadBytes(4);
                fieldHeaders[i].FieldLength = dbfReader.ReadByte();
                byte[] reserved2 = dbfReader.ReadBytes(15);
            }
            byte headerTerminator = dbfReader.ReadByte();
            //13

            if (sFieldId == "")
                sFieldId = fieldHeaders[0].FieldName;
            if (sFieldLabel == "")
            {
                if (fieldHeaders.Length > 1)
                {
                    sFieldLabel = fieldHeaders[1].FieldName;
                }
                else
                {
                    sFieldLabel = fieldHeaders[0].FieldName;
                }
            }

            string AreaId;
            string AreaName;
            for (i = 0; i <= numberRecords - 1; i++)
            {
                byte isValid = dbfReader.ReadByte();
                //32
                DataRow _Row = _DT.NewRow();
                for (j = 0; j <= fieldHeaders.Length - 1; j++)
                {
                    char[] fieldDataChars = dbfReader.ReadChars(fieldHeaders[j].FieldLength);
                    if (fieldHeaders[j].FieldName == sFieldId)
                    {
                        AreaId = new string(fieldDataChars).Trim();
                        AreaId = AreaId.Substring(0, Math.Min(AreaId.Length, _DT.Columns[0].MaxLength));
                        //Limit the string to MaxLength
                        _Row["AreaId"] = AreaId;
                    }
                    else if (fieldHeaders[j].FieldName == sFieldLabel)
                    {
                        AreaName = new string(fieldDataChars).Trim();
                        AreaName = AreaName.Substring(0, Math.Min(AreaName.Length, _DT.Columns[1].MaxLength));
                        //Limit the string to MaxLength
                        _Row["AreaName"] = AreaName;
                    }
                    string fieldData = new string(fieldDataChars).Trim();
                }
                _DT.Rows.Add(_Row);
                _Row = null;
            }

            dbfStream.Close();
            dbfStream = null;
            dbfReader.Close();
            dbfReader = null;
            return _DT;
        }