|||
自己写了个读取shape格式的文档,希望各位专家指导
Shape 头文件结构分析
起止位置字段名称字段的值类型字节顺序
0-3 file code 9994 Integer
4-23 保留字 0 Integer
24-27 文件长度 Integer 高位
28-31 版本号 Integer
32-35 图形类型 Integer
36-43 Bunding Box Xmin Double
44-51 Bunding Box Ymin Double
52-59 Bunding Box Xmax Double
60-67 Bunding Box Ymax Double
接着是记录头信息,记录头信息和记录数据信息是循环的。每一条记录都包括记录头信息+记录数据信息。
记录的头信息是固定的长度,而记录数据信息根据不同的记录结构体的不同而变化。但是,每种结构体的结构是固定的。
Shape 记录条文头信息分析
主文件记录头的描述
Positoin Filed Value Type Oreder
0-3 记录编号 Integer Big
4-7 该记录的长度 Integer Big
Shape的数据记录条文内容是由 shape类型和shape的结构体数据组成。每一种shape类型,都是先描述,然后再把记录内容记录在磁盘上的。描述信息就是头信息包括的编号和长度。
下面以PolyLine 为例说明一下,数据存储结构。
Positoin Filed Value Type Oreder
0-3 记录编号 Integer Big
4-7 该记录的长度 Integer Big
8-11 类型ShapeType Value=3 Little
12-35 Box Bounding 4*Double Little
36-39 NumParts Integer Little
40-43 NumPoints Integer Little
44-47 Integer[Num]Parts Integer Little
ByteX-Y Integer[NumPoints]Points Integer Little
Note: X= 44+4*NumParts
Y= X+NumPoints*16(x、y坐标都是一个double)
因此,解析一个完整的Shape文件。首先是解析头信息,获得重要的 Shape 类型,根据Shape类型来解析记录条文信息。数据都是以16进制记录,没有空格。
头信息占据前99个字节,
读取shape头文件信息(一下的读取是依次读取)
br.RedBytes(24);//头二十四个大部分是保留位。
intFileLength = br.ReadInt32();//<0代表数据长度未知
FileLength这里是高位需要转换一下。
intFileBanben = br.ReadInt32();
ShapeType = br.ReadInt32();
xmin = br.ReadDouble();
ymin = br.ReadDouble();
xmax = br.ReadDouble();
ymax = br.ReadDouble();
br.ReadBytes(32); --读取到99个字节,头信息读取完毕
ulongbig2little(int code) //将big位序转换为little位序
{
ulong value;
value = ((((ulong)(code) & (ulong)0x000000ffUL)<< 24) | (((ulong)(code) & (ulong)0x0000ff00UL) << 8) | (((ulong)(code) & (ulong)0x00ff0000UL)>> 8) | (((ulong)(code) & (ulong)0xff000000UL) >> 24));
returnvalue;
}
例如:读取头信息,需要高位转低位。
intRecordNum = br.ReadInt32();
RecordNum = Convert.ToInt32(big2little(RecordNum));
intDataLength = br.ReadInt32();
DataLength= Convert.ToInt32(big2little(DataLength));
头信息读取完毕了,接着就是根据shapeType 来读取接下来的存储的数据。
以读取线类型信息为例说明(一条完整的记录包括记录条文的头信息和多段线数据结构信息)
structPolyLine_shape // 使用该结构体来表示多段线的信息结构
{
publicdouble[] Box; //边界盒
publicintNumParts; //部分的数目
publicintNumPoints; //点的总数目
publicArrayListParts; //在部分中第一个点的索引
publicArrayListPoints; //所有部分的点
}
PolyLine_shapepolyline = newPolyLine_shape();//实例化一个多段线
|
RecordNum = Convert.ToInt32(big2little(RecordNum));
intDataLength = br.ReadInt32();
DataLength = Convert.ToInt32(big2little(DataLength));
Int ShapeType =br.ReadInt32(); // 读取本条记录的shape类型
polyline.Box[0] = br.ReadDouble();//xmin
polyline.Box[1] = br.ReadDouble();//ymin
polyline.Box[2] = br.ReadDouble();//xmax
polyline.Box[3] = br.ReadDouble();//ymax
polyline.NumParts = br.ReadInt32();//组成多段线部分数量
polyline.NumPoints = br.ReadInt32();//组成该多段线总的特征点数
//接着的数据存储的是各个组成多段线各部分第一个点在总point集合中的位置。
//他是一个长度为NumParts 的数组,所以一下使用一个for循环来将这些点的索引位置信息读出来,并存储在结构体中
for(int i = 0; i < polyline.NumParts; i++)
{
int parts = newint();
parts = br.ReadInt32();
polyline.Parts.Add(parts);
}
//读完点的索引信息后,就是点的信息,由于点的信息也是就是长度为Numpoints
的数组。所以,使用for循环来分别读取,并实例化成点添加到多段线的实例中去。
structPoint_shape // 定义点的结构体
{
publicdoubleX;
publicdoubleY;
}
for(int j = 0; j < polyline.NumPoints; j++)
{
Point_shape pointtemp = newPoint_shape();//实例化点
pointtemp.X = br.ReadDouble();
pointtemp.Y = br.ReadDouble();
polyline.Points.Add(pointtemp); //将点的信息添加到多段线的实例中
}
//以上的头信息和数据信息组成了一条完整的记录。
//接下来的数据都是重复上述的信息结构。
//因此整体要读取所有的记录信息的话就需要按照以下的方法来依次读取。
//还是以读取ployline为例来读取
//1、 读取shape文件的头信息。
// BinaryReader br = new BinaryReader(openFileDialog1.OpenFile());
// br.read(99);读取前99个字节,就可以将头信息读取完。
ArrayList polylines = newArrayList();//创建一个容器,用于存储多条记录的数组
polylines.Clear();
//2、逐条读取记录的条文信息
While(br.PeekChar() != -1){ // br是指的数据流
PolyLine_shape polyline = newPolyLine_shape();//实例化一个多段线
//读取头信息
//读取数据信息
polylines.Add(polyline);
}
// 最终获得polylines中包含了所有的多段线的信息。
//采用如下方法可以将获得的信息写入到文本中。
Public WritePloyLineInfoToTxt(){
StreamWritersw2 = newStreamWriter("line.txt");
count = 1;
foreach (PolyLine_shapep in polylines)
{
for (inti = 0; i < p.NumParts; i++){
intstartpoint;
int endpoint;
if(i == p.NumParts - 1)
{
startpoint = (int)p.Parts[i];
endpoint = p.NumPoints;
}
else
{
startpoint = (int)p.Parts[i];
endpoint = (int)p.Parts[i + 1];
}
sw2.WriteLine("线" + count.ToString() + ":");
for(j = startpoint; j < endpoint; j++)
{
Point_shapeps = (Point_shape)p.Points[j];
sw2.WriteLine("{0},{1},{2} ", ps.X, ps.Y, 0);
}
count++;
}
}
sw2.Close();
}
以上代码可以直接复制到程序中直接使用,解析shape 格式数据,需要更多的
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-6-16 06:20
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社