shapefile格式说明及读写代码示例

(十)Shapefile文件创建——创建Shapefile和dBASE 创建Shapefile和dBASE 阅读详情
Shape files数据说明
Shape files是ESRI提供的一种矢量数据格式,它没有拓扑信息,一个Shape files由一组文件组成,其中必要的基本文件包括坐标文件(.shp)、索引文件(.shx)和属性文件(.dbf)三个文件。
坐标文件的结构说明
坐标文件(.shp)用于记录空间坐标信息。它由头文件和实体信息两部分构成(如图2.1所示)。
坐标文件的文件头
坐标文件的文件头是一个长度固定(100 bytes)的记录段,一共有9个int型和7个double型数据,主要记录内容见表2.2。
文件头
记录头
记录内容
记录头
记录内容
记录头
记录内容
记录头
记录内容
……
……
记录头
记录内容
图2.1 坐标文件的结构
起始位置
名称
数值
类型
位序
0
File Code
9994
Integer
big
4
Unused
0
Integer
big
8
Unused
0
Integer
big
12
Unused
0
Integer
big
16
Unused
0
Integer
big
20
Unused
0
Integer
big
24
文件长度
文件的实际长度
Integer
big
28
版本号
1000
Integer
Little
32
几何类型
表示这个Shapefile文件所记录的空间数据的几何类型
Integer
Little
36
Xmin
空间数据所占空间范围的X方向最小值
Double
Little
44
Ymin
空间数据所占空间范围的Y方向最小值
Double
Little
52
Xmax
空间数据所占空间范围的X方向最大值
Double
Little
60
Ymax
空间数据所占空间范围的Y方向最大值
Double
Little
68*
Zmin
空间数据所占空间范围的Z方向最小值
Double
Little
76*
Zmax
空间数据所占空间范围的Z方向最大值
Double
Little
84*
Mmin
最小Measure值
Double
Little
92*
Mmax
最大Measure值
Double
Little
表2.2shapefiles 头文件表
注:最后4个加星号特别标示的四个数据只有当这个Shapefile文件包含Z方向坐标或者具有Measure值时才有值,否则为0.0。所谓Measure值,是用于存储需要的附加数据,可以用来记录各种数据,例如权值、道路长度等信息。
位序
细心的读者会注意到表2.2中的数值的位序有Little和big的区别,对于位序是big的数据我们在读取时要小心。通常,数据的位序都是Little,但在有些情况下可能会是big,二者的区别在于它们位序的顺序相反。一个位序为big的数据,如果我们想得到它的真实数值,需要将它的位序转换成Little即可。转换原理非常简单,就是交换字节顺序,下面是作者实现的在两者间进行转换的程序,代码如下:
//位序转换程序
unsigned long OnChangeByteOrder (int indata)
{
       char ss[8];
       char ee[8];
       unsigned long val = unsigned long(indata);
       _ultoa( val, ss, 16 );//将十六进制的数(val)转到一个字符串(ss)中
       int i;
       int length=strlen(ss);
       if(length!=8)
       {
              for(i=0;i<8-length;i++)
                     ee[i]='0';
              for(i=0;i<length;i++)
                     ee[i+8-length]=ss[i];
              for(i=0;i<8;i++)
                     ss[i]=ee[i];
       }
       ////******进行倒序
       int t;
       t      =ss[0];
       ss[0]       =ss[6];
       ss[6]       =t;
       t      =ss[1];
       ss[1]       =ss[7];
       ss[7]       =t;
       t      =ss[2];
       ss[2]       =ss[4];
       ss[4]       =t;
       t      =ss[3];
       ss[3]       =ss[5];
       ss[5]       =t;
    ////******
       //******将存有十六进制数(val)的字符串(ss)中的十六进制数转成十进制数
       int value=0;
       for(i=0;i<8;i++)
       {
              int k;
              CString mass;
              mass=ss[i];
              if(ss[i]=='a' ||
                 ss[i]=='b' ||
                 ss[i]=='c' ||
                 ss[i]=='d' ||
                 ss[i]=='e' ||
                 ss[i]=='f')
                     k=10+ss[i]-'a';
              else
                     sscanf(mass,"%d",&k);
              value=value+int(k*pow(16,7-i));
       }
       return (value);
}
Shapefile文件支持的几何类型(ShapeType)
Shapefile文件所支持的几何类型如表2.3所示:
编号
几何类型
0
Null Shape(表示这个Shapefile文件不含坐标)
1
Point(表示Shapefile文件记录的是点状目标,但不是多点)
3
PolyLine(表示Shapefile文件记录的是线状目标)
5
Polygon(表示Shapefile文件记录的是面状目标)
8
MultiPoint(表示Shapefile文件记录的是多点,即点集合)
11
PointZ(表示Shapefile文件记录的是三维点状目标)
13
PolyLineZ(表示Shapefile文件记录的是三维线状目标)
15
PolygonZ(表示Shapefile文件记录的是三维面状目标)
18
MultiPointZ(表示Shapefile文件记录的是三维点集合目标)
21
PointM(表示含有Measure值的点状目标)
23
PolyLineM(表示含有Measure值的线状目标)
25
PolygonM(表示含有Measure值的面状目标)
28
MultiPointM(表示含有Measure值的多点目标)
31
MultiPatch(表示复合目标)
表2.3shapefiles文件支持的几何类型
对于一个不是记录Null Shape类型的Shapefile文件,它所记录的空间目标的几何类型必须一致,不能在一个Shapefile文件中同时记录两种不同类型的几何目标。
读取坐标文件(.shp)的文件头的代码如下:
void OnReadShp(CString ShpFileName)
{
       FILE*   m_ShpFile_fp;       //****Shp文件指针
//打开坐标文件
       if((m_ShpFile_fp=fopen(ShpFileName,"rb"))==NULL)
       {
              return;
       }
       //读取坐标文件头的内容开始
       int FileCode;
       int Unused;
       int FileLength;
       int Version;
       int ShapeType;
       double Xmin;
       double Ymin;
       double Xmax;
       double Ymax;
       double Zmin;
       double Zmax;
       double Mmin;
       double Mmax;
       fread(&FileCode,     sizeof(int),   1,m_ShpFile_fp);
       FileCode = OnChangeByteOrder(FileCode);
       for(i=0;i<5;i++)
              fread(&Unused,sizeof(int),   1,m_ShpFile_fp);
       fread(&FileLength,   sizeof(int),   1,m_ShpFile_fp);
       FileLength      = OnChangeByteOrder(FileLength);
       fread(&Version,          sizeof(int),   1,m_ShpFile_fp);
       fread(&ShapeType,    sizeof(int),   1,m_ShpFile_fp);
       fread(&Xmin,         sizeof(double),1,m_ShpFile_fp);
       fread(&Ymin,         sizeof(double),1,m_ShpFile_fp);
       fread(&Xmax,         sizeof(double),1,m_ShpFile_fp);
       fread(&Ymax,         sizeof(double),1,m_ShpFile_fp);
       fread(&Zmin,         sizeof(double),1,m_ShpFile_fp);
       fread(&Zmax,        sizeof(double),1,m_ShpFile_fp);
       fread(&Mmin,         sizeof(double),1,m_ShpFile_fp);
       fread(&Mmax,         sizeof(double),1,m_ShpFile_fp);
       //读取坐标文件头的内容结束
       //根据几何类型读取实体信息
       ……
}
实体信息的内容
实体信息负责记录坐标信息,它以记录段为基本单位,每一个记录段记录一个地理实体目标的坐标信息,每个记录段分为记录头和记录内容两部分。
记录头的内容包括记录号(Record Number)和坐标记录长度(Content Length) 两个记录项。它们的位序都是big。记录号(Record Number)和坐标记录长度(Content Length) 两个记录项都是int型,并且shapefile文件中的记录号都是从1开始的。
记录内容包括目标的几何类型(ShapeType)和具体的坐标记录(X、Y) ,记录内容因要素几何类型的不同其具体的内容及格式都有所不同。下面分别介绍点状目标(Point)、线状目标(PolyLine)和面状目标(Polygon)三种几何类型的.shp文件的记录内容:
点状目标
shapefile中的点状目标由一对X、Y坐标构成,坐标值为双精度型(double)。点状目标的记录内容如表2.4:
记录项
数值
数据类型
长度
个数
位序
几何类型(ShapeType)
1(表示点状目标)
int型
4
1
Little
X方向坐标
X方向坐标值
double型
8
1
Little
Y方向坐标
Y方向坐标值
double型
8
1
Little
表2.4点状目标的记录内容
下面是读取点状目标的记录内容的代码:
OnReadPointShp(CString ShpFileName)
{
       //打开坐标文件
       ……
       //读取坐标文件头的内容开始
       ……
       //读取点状目标的实体信息
       int RecordNumber;
       int ContentLength;
       int num   =0;
       while((fread(&RecordNumber,    sizeof(int),   1,ShpFile_fp)!=0))
       {
              num++;
              fread(&ContentLength,sizeof(int),   1,ShpFile_fp);
              RecordNumber      = OnChangeByteOrder(RecordNumber);
              ContentLength       = OnChangeByteOrder(ContentLength);
              int shapeType;
              double x;
double y;
              fread(&shapeType, sizeof(int),   1,ShpFile_fp);
              fread(&x, sizeof(double),   1,ShpFile_fp);
              fread(&y, sizeof(double),   1,ShpFile_fp);
}
}
线状目标
shapefile中的线状目标是由一系列点坐标串构成,一个线目标可能包括多个子线段,子线段之间可以是相离的,同时子线段之间也可以相交。Shapefile允许出现多个坐标完全相同的连续点,当读取文件时一定要注意这种情况,但是不允许出现某个退化的、长度为0的子线段出现。线状目标的记录内容如表2.5:
记录项
数值
数据类型
长度
个数
位序
几何类型(ShapeType)
3(表示线状目标)
int型
4
1
Little
坐标范围(Box)
表示当前线目标的坐标范围
double型
32
4
Little
子线段个数(NumParts)
表示构成当前线目标的子线段的个数
int型
4
1
Little
坐标点数(NumPoints)
表示构成当前线目标所包含的坐标点个数
int型
4
1
Little
Parts数组
记录了每个子线段的坐标在Points数组中的起始位置
int型
4×NumParts
NumParts
Little
Points数组
记录了所有的坐标信息
Point型
根据点个数来确定
NumPoints
Little
表2.5线状目标的记录内容
具体的数据结构如下:
PolyLine
{
Double[4]               Box               // 当前线状目标的坐标范围
Integer                   NumParts     // 当前线目标所包含的子线段的个数
Integer                   NumPoints   // 当前线目标所包含的顶点个数
Integer[NumParts]  Parts              // 每个子线段的第一个坐标点在Points的位置
Point[NumPoints]    Points             // 记录所有坐标点的数组
}
这些记录项的具体含义如下:
Box记录了当前的线目标的坐标范围,它是一个double型的数组,按照Xmin、 Ymin、 Xmax、Ymax的顺序记录了坐标范围;
NumParts记录了当前线目标所包含的子线段的个数;
NumPoints记录了当前线目标的坐标点总数;
Parts记录了每个子线段的第一个坐标点在坐标数组points中的位置,以便读取数据;
Points是用于存放当前线目标的X、Y坐标的数组。
下面是读取线状目标的记录内容的代码:
OnReadLineShp(CString ShpFileName)
{
       //打开坐标文件
       ……
       //读取坐标文件头的内容开始
       ……
       //读取线状目标的实体信息
       int RecordNumber;
       int ContentLength;
       int num   =0;
       while((fread(&RecordNumber,    sizeof(int),   1,ShpFile_fp)!=0))
       {
              fread(&ContentLength,sizeof(int),   1,ShpFile_fp);
              RecordNumber      = OnChangeByteOrder (RecordNumber);
              ContentLength       = OnChangeByteOrder (ContentLength);
              int shapeType;
              double Box[4];
              int NumParts;
              int NumPoints;
              int *Parts;
              fread(&shapeType,    sizeof(int),   1,ShpFile_fp);
              //读Box
              for(i=0;i<4;i++)
                     fread(Box+i,     sizeof(double),1,ShpFile_fp);
              //读NumParts和NumPoints
              fread(&NumParts,     sizeof(int),   1,ShpFile_fp);
              fread(&NumPoints,    sizeof(int),   1,ShpFile_fp);
              //读Parts和Points
              Parts       =new int[NumParts];
              for(i=0;i<NumParts;i++)
                     fread(Parts+i,   sizeof(int),   1,ShpFile_fp);
              int pointNum;
              for(i=0;i<NumParts;i++)
              {
                     if(i!=NumParts-1)
                            pointNum       =Parts[i+1]-Parts[i];
                     else
                            pointNum       =NumPoints-Parts[i];
                     double *PointsX;
                     double *PointsY;
                    
                     PointsX =new double[pointNum];
                     PointsY =new double[pointNum];
                    
                     for(j=0;j<pointNum;j++)
                     {
                            fread(PointsX+j, sizeof(double),1,ShpFile_fp);
                            fread(PointsY+j, sizeof(double),1,ShpFile_fp);
                     }
                     delete[] PointsX;
                     delete[] PointsY;
              }
              delete[] Parts;
       }
}
面状目标
shapefile中的面状目标是由多个子环构成,每个子环是由至少四个顶点构成的封闭的、无自相交现象的环。对于含有岛的多边形,构成它的环有内外环之分,每个环的顶点的排列顺序或者方向说明了这个环到底是内环还是外环。一个内环的顶点是按照逆时针顺序排列的;而对于外环,它的顶点排列顺序是顺时针方向。如果一个多边形只由一个环构成,那么它的顶点排列顺序肯定是顺时针方向。
每条多边形记录的数据结构与线目标的数据结构完全相同,
Polygon
{
Double[4]               Box               // 当前面状目标的坐标范围
Integer                   NumParts     // 当前面目标所包含的子环的个数
Integer                   NumPoints   // 构成当前面状目标的所有顶点的个数
Integer[NumParts]  Parts              // 每个子环的第一个坐标点在Points的位置
Point[NumPoints]    Points             // 记录所有坐标点的数组
}
对于一个shapefile中的多边形,它必须满足下面三个条件:
构成多边形的每个子环都必须是闭合的,即每个子环的第一个顶点跟最后一个顶点是同一个点;
每个子环在Points数组中的排列顺序并不重要,但每个子环的顶点必须按照一定的顺序连续排列;
存储在shapefile 中的多边形必须是干净的。所谓一个干净的多边形,它必须满足两点:
没有自相交现象。这就要求任何一个子环不能跟其它的子环相交,共线的现 象也将被当作相交。但是允许两个子环的顶点重合;
对于一个不含岛的多边形或者是含岛的多边形的外环,它们的顶点排列顺序必须是顺时针方向;而对于内环,它的排列顺序必须是逆时针方向。所谓的“脏多边形”就是指顶点排列顺序为顺时针的内环。
图2.2中的多边形是一个典型的例子。这个多边形包括一个岛,所有顶点的个数为8。NumParts等于2,NumPoints等于10。请注意内环(岛)的顶点的排列顺序是逆时针的(如图2.3所示)。
图2.2 带岛的多边形

0
0
5
5
v1
0
v2
 
1
v3
 
2
v4
 
3
v1
 
4
v5
 
5
v8
 
6
v7
 
7
v6
 
8
v5
 
9

图2.3 带岛的多边形的坐标记录
面状目标的记录内容如表2.6:
记录项
数值
数据类型
长度
个数
位序
几何类型(ShapeType)
5(表示面状目标)
int型
4
1
Little
坐标范围(Box)
表示当前面目标的坐标范围
double型
32
4
Little
子线段个数(NumParts)
表示构成当前面状目标的子环的个数
int型
4
1
Little
坐标点数(NumPoints)
表示构成当前面状目标所包含的坐标点个数
int型
4
1
Little
Parts数组
记录了每个子环的坐标在Points数组中的起始位置
int型
4×NumParts
NumParts
Little
Points数组
记录了所有的坐标信息
Point型
根据点个数来确定
NumPoints
Little
表2.6面状目标的记录内容
下面是读取面状目标的记录内容的代码:
void OnReadAreaShp(CString ShpFileName)
{
       //打开坐标文件
       ……
       //读取坐标文件头的内容开始
       ……
       //读取面状目标的实体信息
       int RecordNumber;
       int ContentLength;
       while((fread(&RecordNumber,    sizeof(int),   1,m_ShpFile_fp)!=0))
       {
              fread(&ContentLength,sizeof(int),   1,m_ShpFile_fp);
              RecordNumber      = OnChangeByteOrder (RecordNumber);
              ContentLength       = OnChangeByteOrder (ContentLength);
              int shapeType;
              double Box[4];
              int NumParts;
              int NumPoints;
              int *Parts;
              fread(&shapeType,    sizeof(int),   1,m_ShpFile_fp);
              //读Box
              for(i=0;i<4;i++)
                     fread(Box+i,     sizeof(double),1,m_ShpFile_fp);
              //读NumParts和NumPoints
              fread(&NumParts,     sizeof(int),   1,m_ShpFile_fp);
              fread(&NumPoints,    sizeof(int),   1,m_ShpFile_fp);
              //读Parts和Points
              Parts       =new int[NumParts];
              for(i=0;i<NumParts;i++)
                     fread(Parts+i,   sizeof(int),   1,m_ShpFile_fp);
              int pointNum;
              int xx;
              int yy;
              for(i=0;i<NumParts;i++)
              {
                     if(i!=NumParts-1)
                            pointNum       =Parts[i+1]-Parts[i];
                     else
                            pointNum       =NumPoints-Parts[i];
                    
                     double *PointsX;
                     double *PointsY;
                    
                     PointsX =new double[pointNum];
                     PointsY =new double[pointNum];
                    
                     for(j=0;j<pointNum;j++)
                     {
                            fread(PointsX+j, sizeof(double),1,m_ShpFile_fp);
                            fread(PointsY+j, sizeof(double),1,m_ShpFile_fp);
                     }
                     delete[] PointsX;
                     delete[] PointsY;
              }
              delete[] Parts;
       }
}
属性文件的结构说明
属性文件(.dbf)用于记录属性信息。它是一个标准的DBF文件,也是由头文件和实体信息两部分构成(如图2.4所示)。
文件头
记录1
 
记录2
 
记录3
 
记录4
 
……
……
记录n
图2.4 属性文件的结构
属性文件的文件头
其中文件头部分的长度是不定长的,它主要对DBF文件作了一些总体说明(见表2.7),其中最主要的是对这个DBF文件的记录项的信息进行了详细地描述,比如对每个记录项的名称、数据类型、长度等信息都有具体的说明。
在文件中的位置
内容
说明
0
1个字节
表示当前的版本信息
1-3
3个字节
表示最近的更新日期,按照YYMMDD格式。
4-7
1个32位数
文件中的记录条数。
8-9
1个16位数
文件头中的字节数。
10-11
1个16位数
一条记录中的字节长度。
12-13
2个字节
保留字节,用于以后添加新的说明性信息时使用,这里用0来填写。
14
1个字节
表示未完成的操作。
15
1个字节
dBASE IV编密码标记。
16-27
12个字节
保留字节,用于多用户处理时使用。
28
1个字节
DBF文件的MDX标识。在创建一个DBF 表时,如果使用了MDX 格式的索引文件,那么 DBF 表的表头中的这个字节就自动被设置了一个标志,当你下次试图重新打开这个DBF表的时候,数据引擎会自动识别这个标志,如果此标志为真,则数据引擎将试图打开相应的MDX 文件。
29
1个字节
Language driver ID.
30-31
2个字节
保留字节,用于以后添加新的说明性信息时使用,这里用0来填写。
32-X
(n*32)个字节
记录项信息描述数组。n表示记录项的个数。这个数组的结构在表2.8中有详细的解释。
X+1
1个字节
作为记录项终止标识。
表2.7属性文件(.dbf)的文件头
位置
内容
说明
0-10
11个字节
记录项名称,是ASCII码值。
11
1个字节
记录项的数据类型,是ASCII码值。(B、C、D、G、L、M和N,具体的解释见表2.9)。
12-15
4个字节
保留字节,用于以后添加新的说明性信息时使用,这里用0来填写。
16
1个字节
记录项长度,二进制型。
17
1个字节
记录项的精度,二进制型。
18-19
2个字节
保留字节,用于以后添加新的说明性信息时使用,这里用0来填写。
20
1个字节
工作区ID。
21-30
10个字节
保留字节,用于以后添加新的说明性信息时使用,这里用0来填写。
31
1个字节
MDX标识。如果存在一个MDX 格式的索引文件,那么这个记录项为真,否则为空。
表2.8记录项信息描述
代码
数据类型
允许输入的数据
B
二进制型
各种字符。
C
字符型
各种字符。
D
日期型
用于区分年、月、日的数字和一个字符,内部存储按照YYYYMMDD格式。
G
(General
or OLE)
各种字符。
N
数值型(Numeric)
- . 0 1 2 3 4 5 6 7 8 9
L
逻辑型(Logical)
? Y y N n T t F f (? 表示没有初始化)。
M
(Memo)
各种字符。
表2.9dbf文件中的数据类型
属性文件的实体信息
实体信息部分就是一条条属性记录,每条记录都是由若干个记录项构成,因此只要依次循环读取每条记录就可以了。
一个读取dbf文件的例子
假设要读取一个名为soil的dbf文件(存储了土地利用信息),它含有8个记录项,记录项信息如表2.10所示:
记录项名称
数据类型
长度
小数位数
Area
数值型(double)
31
15
Perimeter
数值型(double)
31
15
soils_
数值型(int)
11
0
soils_id
数值型(int)
11
0
soil_code
字符型(character)
3
无
Suit
字符型(character)
1
无
Centroid_x
数值型(double)
31
15
Centroid_y
数值型(double)
31
15
表2.10dbf文件中的数据类型
下面是读取这个dbf文件的代码:
void OnReadDbf(CString DbfFileName)
{
       FILE*   m_DbfFile_fp;       //****Dbf文件指针
       //打开dbf文件
       if((m_DbfFile_fp=fopen(DbfFileName,"rb"))==NULL)
       {
              return;
       }
       int i,j;
       //////****读取dbf文件的文件头  开始
       BYTE version;
       fread(&version,     1,   1,m_DbfFile_fp);
      
       BYTE date[3];
       for(i=0;i<3;i++)
       {
              fread(date+i,     1,   1,m_DbfFile_fp);
       }
      
       int RecordNum;            //******
       fread(&RecordNum,         sizeof(int),   1,m_DbfFile_fp);
       short HeaderByteNum;
       fread(&HeaderByteNum, sizeof(short), 1,m_DbfFile_fp);
       short RecordByteNum
       fread(&RecordByteNum, sizeof(short), 1,m_DbfFile_fp);
       short Reserved1;          
       fread(&Reserved1,    sizeof(short), 1,m_DbfFile_fp);
      
       BYTE Flag4s;
       fread(&Flag4s,                 sizeof(BYTE), 1,m_DbfFile_fp);
       BYTE EncrypteFlag;
       fread(&EncrypteFlag,            sizeof(BYTE), 1,m_DbfFile_fp);
      
       for(i=0;i<3;i++)
       {
              fread(&Unused,        sizeof(int),   1,m_DbfFile_fp);
       }
       BYTE MDXFlag;
       fread(&MDXFlag,    sizeof(BYTE), 1,m_DbfFile_fp);
      
       BYTE LDriID;
       fread(&LDriID,                sizeof(BYTE), 1,m_DbfFile_fp);
       short Reserved2;
       fread(&Reserved2,    sizeof(short), 1,m_DbfFile_fp);
       BYTE name[11];
       BYTE fieldType;
       int Reserved3;
       BYTE fieldLength;
       BYTE decimalCount;
       short Reserved4;
       BYTE workID;
       short Reserved5[5];
       BYTE mDXFlag1;
       int fieldscount;
       fieldscount = (HeaderByteNum - 32) / 32;
       //读取记录项信息-共有8个记录项
       for(i=0;i< HeaderByteNum;i++)
       {
              //FieldName----11   bytes
              fread(name,    11, 1,m_DbfFile_fp);
              //FieldType----1     bytes
              fread(&fieldType,   sizeof(BYTE), 1,m_DbfFile_fp);
              //Reserved3----4     bytes
              Reserved3      =0;
              fread(&Reserved3, sizeof(int), 1,m_DbfFile_fp);
              //FieldLength--1     bytes
              fread(&fieldLength,sizeof(BYTE), 1,m_DbfFile_fp);
              //DecimalCount-1   bytes
              fread(&decimalCount,sizeof(BYTE), 1,m_DbfFile_fp);
              //Reserved4----2     bytes
              Reserved4      =0;
              fread(&Reserved4, sizeof(short), 1,m_DbfFile_fp);
              //WorkID-------1    bytes
              fread(&workID,            sizeof(BYTE), 1,m_DbfFile_fp);
              //Reserved5----10   bytes
              for(j=0;j<5;j++)
              {
                     fread(Reserved5+j,sizeof(short), 1,m_DbfFile_fp);
              }
              //MDXFlag1-----1 bytes
              fread(&mDXFlag1,       sizeof(BYTE), 1,m_DbfFile_fp);
       }
       BYTE terminator;
       fread(&terminator,        sizeof(BYTE), 1,m_DbfFile_fp);
       //读取dbf文件头结束
       double Area,Perimeter,Centroid_y,Centroid_x;
       int Soils_,Soils_id;
       CString Soil_code,suit;
       BYTE   deleteFlag;
       char media[31];
       //读取dbf文件记录 开始
       for(i=0;i<RecordNum;i++)
       {
              fread(&deleteFlag, sizeof(BYTE), 1,m_DbfFile_fp);
              //读取 Area double
              for(j=0;j<31;j++)
                     fread(media+j, sizeof(char), 1,m_DbfFile_fp);
              Area =atof(media);
              //读取 Perimeter double
              for(j=0;j<31;j++)
                     fread(media+j, sizeof(char), 1,m_DbfFile_fp);
              Perimeter =atof(media);
              //读取 soils_ int
              for(j=0;j<31;j++)
                     strcpy(media+j,"");
              for(j=0;j<11;j++)
                     fread(media+j, sizeof(char), 1,m_DbfFile_fp);
              Soils_      =atoi(media);
              //读取 Soils_id int
              for(j=0;j<31;j++)
                     strcpy(media+j,"");
              for(j=0;j<11;j++)
                     fread(media+j, sizeof(char), 1,m_DbfFile_fp);
              Soils_id   =atoi(media);
              //读取 soil_code string
              for(j=0;j<31;j++)
                     strcpy(media+j,"");
              for(j=0;j<3;j++)
                     fread(media+j, sizeof(char), 1,m_DbfFile_fp);
              Soil_code       =media;
              //读取 suit string
              for(j=0;j<31;j++)
                     strcpy(media+j,"");
              for(j=0;j<1;j++)
                     fread(media+j, sizeof(char), 1,m_DbfFile_fp);
              suit =media;
              //读取 Centroid_y double
              for(j=0;j<31;j++)
                     strcpy(media+j,"");
              for(j=0;j<31;j++)
                     fread(media+j, sizeof(char), 1,m_DbfFile_fp);
              Centroid_y      =atof(media);
              //读取 Centroid_x double
              for(j=0;j<31;j++)
                     strcpy(media+j,"");
              for(j=0;j<31;j++)
                     fread(media+j, sizeof(char), 1,m_DbfFile_fp);
              Centroid_x      =atof(media);
       }
       //读取dbf文件记录 结束
}
索引文件的结构说明
索引文件(.shx)主要包含坐标文件的索引信息,文件中每个记录包含对应的坐标文件记录距离坐标文件的文件头的偏移量。通过索引文件可以很方便地在坐标文件中定位到指定目标的坐标信息。
索引文件也是由头文件和实体信息两部分构成(如图2.5),其中文件头部分是一个长度固定(100 bytes)的记录段,其内容与坐标文件的文件头基本一致。它的实体信息以记录为基本单位,每一条记录包括偏移量(offset)和记录段长度(Content Length)两个记录项,它们的位序都是big,两个记录项都是int型,见表2.11。
文件头
记录1
 
记录2
 
记录3
 
记录4
 
……
……
记录n
图2.5 索引文件的结构
记录项
数值
数据类型
长度
个数
位序
位移量(Offset)
表示坐标文件中的对应记录的起始位置相对于坐标文件起始位置的位移量。
int型
4
1
Big
记录长度
(Content Length)
表示坐标文件中的对应记录的长度。
int型
4
1
Big
表2.11 索引文件的记录内容
下面是一段读取索引文件的代码:
void OnReadShx(CString ShxFileName)
{
       FILE*   m_ShxFile_fp;       //****Shx文件指针
       //打开索引文件
       if((m_ShxFile_fp=fopen(ShxFileName,"rb"))==NULL)
       {
              return;
       }
       //读取索引文件头的内容开始
       int FileCode;
       int Unused;
       int FileLength;
       int Version;
       int ShapeType;
       double Xmin;
       double Ymin;
       double Xmax;
       double Ymax;
       double Zmin;
       double Zmax;
       double Mmin;
       double Mmax;
       fread(&FileCode,     sizeof(int),   1,m_ShxFile_fp);
       FileCode = OnChangeByteOrder(FileCode);
       for(i=0;i<5;i++)
              fread(&Unused,sizeof(int),   1,m_ShxFile_fp);
       fread(&FileLength,   sizeof(int),   1,m_ShxFile_fp);
       FileLength      = OnChangeByteOrder(FileLength);
       fread(&Version,          sizeof(int),   1,m_ShxFile_fp);
       fread(&ShapeType,    sizeof(int),   1,m_ShxFile_fp);
       fread(&Xmin,         sizeof(double),1,m_ShxFile_fp);
       fread(&Ymin,         sizeof(double),1,m_ShxFile_fp);
       fread(&Xmax,         sizeof(double),1,m_ShxFile_fp);
       fread(&Ymax,         sizeof(double),1,m_ShxFile_fp);
       fread(&Zmin,         sizeof(double),1,m_ShxFile_fp);
       fread(&Zmax,        sizeof(double),1,m_ShxFile_fp);
       fread(&Mmin,         sizeof(double),1,m_ShxFile_fp);
       fread(&Mmax,         sizeof(double),1,m_ShxFile_fp);
       //读取索引文件头的内容结束
      
              int Offset, ContentLength;
       //读取实体信息
       while((fread(&Offset,    sizeof(int),   1, m_ShxFile_fp)!=0))
       {
              fread(&ContentLength,sizeof(int),   1, m_ShxFile_fp);
              Offset            = OnChangeByteOrder(Offset);
              ContentLength       = OnChangeByteOrder(ContentLength);
       }
}
小结
本节介绍了MapObjects支持的各种数据,并详细介绍了shapefiles的文件结构,同时给出了读取shapefiles的坐标文件(.shp)、属性文件(.dbf)和索引文件(.shx)的程序,给出这些程序的目的在于让读者通过这些例子深入掌握shapefiles文件的格式,进而具备将特定格式的数据文件转换成shapefiles文件的能力。
 
Python 中有哪些库可以帮助读取和操作 shapefile 文件? Python操作Shapefile文件库推荐 阅读详情

相关推荐

ArcGIS笔记1_如何为shapefile要素定义坐标系

本博文内容主要讲了如何为shapefile要素定义坐标系。

晏长街的博客 8804

OpenGL实现shapefile的绘制

课程采用C++进行编码教学,采用OpenGL实现基本的地理信息系统的矢量数据的读取,解析和绘制,实现地理坐标向屏幕坐标的转化,实现常用的WGS84以及墨卡托坐投影方式,实现重要也是基本的地图操作(放大和漫游功能),后介绍proj4投影库的使用.以及在大规模矢量要素绘制上的优化手段,三种优化手段叠加优化,提升系统性能.

QGIS实现shape、geojson数据的矢量切片教程

如果是shape文件必须包含四个必要的文件即:.shp、.dbf、.shx、.prj。能够实现矢量切片的办法有很多,可以使用geoserver,可以使用qgis,当然也可以自己写代码实现。第二项选择图层,qgis支持同时对多个图层进行矢量切片,我们点击右侧 的...按钮选择要切片的图层即可。切片的速度极快,也可能是数据比较简单,层级比较小,如果设置层级高的话可能花的时间会更长一些。然后下面的extent是指数据的范围,这个通常能够自动计算出来,点击右侧的鼠标箭头按钮即可。本文我们使用geojson数据。

lz5211314121的博客 4318

shapefile(.shp)空间数据格式详细说明

shapefile(.shp)空间数据格式详细说明 shp空间数据格式详细说明shapefile(.shp)空间数据格式详细说明一.主文件的组织1.主文件头2.主文件记录(1)记录头(2)主文件记录内容1)空 shape2)Point (点)3)MultiPoint (多点)4) Arc(弧段)5)Polygon(面)二.索引文件的组织1.索引文件文件头2.索引记录三.属性文件的组织1.属性文件的文件头2.属性文件的实体信息3.读取属性文件的示例:   ESRI 的 shape 文件由一个主文件(.shp)

fbc3173的博客 2万+

hcaptcha无感验证码逆向实战:从接口分析到环境补全

本文详细解析了hcaptcha无感验证码的逆向实战过程。通过分析核心接口与加密逻辑,重点介绍了采用环境补全策略来模拟真实浏览器环境,从而绕过验证码检测。文章提供了从接口抓包、剖析hsw.js加密核心到使用Node.js搭建模拟环境的完整步骤,为自动化操作提供了一种稳健的解决方案。

weixin_29324401的博客 1156

STK相关总结

STK简介 一.SIM卡应用工具包(SIM Application Toolkit),又名CAT/USAT,它包含一系列终端与SIM卡的交互指令,SIM卡可以应用卡内的小应用程序和终端交互,从而实现增值服务的目的,STK包括三种类,STK-imsi切换,STK –OTA,STK-BIP 功能: (1) Profile download:配置下载,开机初始化SIM卡过程中,终端告诉SIM卡终端支持哪些功能,STK中download指终端将数据发送给SIM卡 (2) Proactive command: 主动式

jingjing_2的博客 3357

Shapefile格式说明及读写代码示例

本节介绍了 MapObjects 支持的各种数据,并详细介绍了 shapefiles 的文件结构,同时给出了读取 shapefiles 的坐标文件( .shp )、属性文件( .dbf )和索引文件( .shx )的程序,给出这些程序的目的在于让读者通过这些例子深入掌握 shapefiles 文件的格式,进而具备将特定格式的数据文件转换成 shapefiles 文件的能力。索引文件( .shx )主要包含坐标文件的索引信息,文件中每个记录包含对应的坐标文件记录距离坐标文件的文件头的偏移量。

tigerhhzz的博客 1486

【2025CVPR】基于脉冲神经网络的能效目标检测模型:Multi-scale Spiking Detector(MSD)深度解析

本文提出了一种创新的多尺度脉冲神经网络目标检测器(MSD),通过生物启发的ONNB模块和MSDF框架实现了高效准确的目标检测。该模型采用端到端直接训练策略,在COCO数据集上达到62.0%mAP的精度,同时仅需7.8M参数和6.43mJ能耗,较传统方法提升2.8%精度并降低82.9%能耗。实验验证了其在小目标检测和事件数据处理的优越性,为边缘计算应用提供了新范式。

hasakie的博客 1109

shapefile格式说明及读写代码示例(C++)(转)

<br />Shapefile格式说明及读写代码示例<br />Shape files 数据说明<br />Shape files 是 ESRI 提供的一种矢量数据格式,它没有拓扑信息,一个 Shape files 由一组文件组成,其中必要的基本文件包括坐标文件( .shp )、索引文件( .shx )和属性文件( .dbf )三个文件。<br />坐标文件的结构说明<br />坐标文件 (.shp) 用于记录空间坐标信息。它由头文件和实体信息两部分构成(如图 2.1 所示)。<br />坐标文件的文件头<

vdvvsvxvcvcxvx的专栏 2027

GBase8a-GDCA认证考试-复习参考题

为提升产品服务水平定期举办GBase产品认证培训,培训更多GBase数据库专业人员,满足用户快速成长的业务需求,建设GBase产品生态。请注意甄别,根据所学知识综合判断,正确率97%(97分)。

weixin_41826637的博客 2375

火车头采集器超级详细图文使用指导(面向新手)

火车采集器·超级详细使用指导

DE的个人原创笔记 1万+

shapefile格式的说明及读写代码示例

Shape files数据说明 Shape files是ESRI提供的一种矢量数据格式,它没有拓扑信息,一个Shape files由一组文件组成,其中必要的基本文件包括坐标文件(.shp)、索引文件(.shx)和属性文件(.dbf)三个文件。 坐标文件的结构说明 坐标文件(.shp)用于记录空间坐标信息。它由头文件和实体信息两部分构成(如图2.1所示)。 坐标文件的文件头 坐标文

Jason 的博客 3957

TI单芯片毫米波雷达1642demo代码走读(一)

今天我们来实际看下代码。 首先使用CCS软件导入demo工程,工程有两个,一个是ARM的工程,工程名是mmw_mss_16xx;另一个是DSP的工程,工程名为mmw_dss_16xx。我们将这两个工程的主函数打开,分别位于mss_main.c和dss_main.c文件中。 先看mss的主函数,代码如下。我为每行代码都加了中文注释和自己的理解。 int main (void) { Task_Params taskPara...

1万+

shapefile格式说明及读写代码示例(VB)(转)

  shapefile格式说明及读写代码示例Shape files数据说明Shape files是ESRI提供的一种矢量数据格式,它没有拓扑信息,一个Shape files由一组文件组成,其中必要的基本文件包括坐标文件(.shp)、索引文件(.shx)和属性文件(.dbf)三个文件。坐标文件的结构说明坐标文件(.shp)用于记录空间坐标信息。它由头文件和实体信息两部分构成(如图

jiangna851122的专栏 2059

2026年Java 开发工程师常见面试简答题

本文整理了Java开发工程师面试常见简答题及详细解析,涵盖Java基础、集合框架、并发编程、JVM等核心考点。主要内容包括:1. Java基础概念:JDK/JRE/JVM区别、面向对象特性、重载与重写、接口与抽象类、String特性等 2. 集合框架:ArrayList/LinkedList区别、HashMap实现原理、线程安全方案、集合类型对比 3. 并发编程:synchronized原理、volatile作用、线程创建方式、线程池参数与策略、死锁处理 4. JVM相关:内存区域划分、垃圾回收算法、类加载

不务正业的猿 371

Python 爬虫实战:抓取百科网站上某个词条的详细信息

百科网站(如维基百科)为用户提供了丰富的知识内容,涵盖了从历史、文化到科技等几乎所有领域的知识。对于需要大量数据进行分析、研究或机器学习项目的开发者而言,抓取这些网站的数据显得尤为重要。通过编写一个 Python 爬虫,我们能够轻松地抓取百科网站上的某个词条及其详细信息,从而获取并整理这些知识内容。本篇博客将深入介绍如何通过 Python 编写爬虫来抓取百科网站(如维基百科)的某个词条的详细信息,包括标题、正文内容、参考文献等。requests:发送 HTTP 请求,获取页面内容。

2201_76125261的博客 1670

Android平台下GDAL库示例下载

Android平台下GDAL库示例下载 去发现同类优质开源项目:https://gitcode.com/ 欢迎来到Android平台下GDAL库示例的下载仓库!这里为您提供了免费的GDAL库资源,您可用来读写shapefile,适用于地理信息系统开发。 关于GDAL库 GDAL(Geospatial Data Abstraction Library)是一个开源的地理空间数据抽象库,主要用于读取和写...

gitblog_06701的博客 712

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

python读写shapefile

shapefile为地图元素矢量数据文件。

SecretGirl的博客 2701

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

shapefile格式说明及读写代码

Shape files数据说明 Shape files是ESRI提供的一种矢量数据格式,它没有拓扑信息,一个Shape files由一组文件组成,其中必要的基本文件包括坐标文件(.shp)、索引文件(.shx)和属性文件(.dbf)三个文件。 坐标文件的结构说明 坐标文件(.shp)用于记录空间坐标信息。它由头文件和实体信息两部分构成(如图2.1所示)。 坐标文件的文件头 坐标...

anxiangfei5381的博客 261

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

pyshp读写shapefile

个人标注: 安装可使用命令:pip install pyshp,使用前:import shapefileGitHub地址(内有英文文档说明) shapefile是GIS中非常重要的一种数据类型,在ArcGIS中被称为要素类(Feature Classes),主要包括点(point)、线(polyline)和多边形(polygon)。Python脚本是ArcGIS官方推荐的脚本语言,通过Python脚本能够很方便的调用ArcGIS中的各种工具和函数批量完成所需操作。本文所介绍的这个库(Python ..

qq_41240287的博客 2005

Shapefile格式详解与读写开源库

一。ESRI Shapefile存储格式 二、转载链接与读写Shapefile的库 https://blog.youkuaiyun.com/wywywywywywy123456/article/details/60144577 读写Shapefile开源库: 1.DotSpatial:https://github.com/DotSpatial 2.ShapefileSharp:https:...

三生三世十里桃花 1180
上一篇: 项目简介
下一篇: arcinfo e00格式详解(转)
Chendy
博客等级 码龄23年 67粉丝 37原创
评论 16
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值