当前位置:   article > 正文

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

shapfile示例文件
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.2 shapefiles 头文件表
注:最后 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.3 shapefiles 文件支持的几何类型
对于一个不是记录 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.9 dbf 文件中的数据类型
属性文件的实体信息
实体信息部分就是一条条属性记录,每条记录都是由若干个记录项构成,因此只要依次循环读取每条记录就可以了。
一个读取 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.10 dbf 文件中的数据类型
下面是读取这个 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 文件的能力。
 
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/310402
推荐阅读
相关标签
  

闽ICP备14008679号