其他分享
首页 > 其他分享> > Shapefile文件读取-文件头

Shapefile文件读取-文件头

作者:互联网

1 介绍

Shapefile文件格式介绍一文中我们介绍了shapefile文件的结构组成,本文主要介绍如何读取shapefile文件头部分,使用的语言是c++。

2 文件头结构

Shapefile文件的文件头是固定长度的,总长度为100个字节,其中4-23字节为未使用部分,其他字段分别描述着当前shapefile文件的各类信息,在编码过程中,我们需要注意文件头中各字段的字节顺序以及类型,特别是File Length字段,这个是16位字表示的,在我们读取完成后需要转换成正常表示。

BytesFieldValueTypeByte Order
0-3File Code9994IntegerBig Endian
4-23Unused0IntegerBig Endian
24-27File LengthFile LengthIntegerBig Endian
28-31Version1000IntegerLittle Endian
32-35Shape TypeShape TypeIntegerLittle Endian
36-67Minimum Bounding RectangleXmin, Ymin, Xmax and YmaxdoubleLittle Endian
68-83Bounding BoxZmin, ZmaxdoubleLittle Endian
84-99Bounding BoxMmin, MmaxdoubleLittle Endian

3 数据结构封装

因为文件头是固定长度的,所以我们可以封装一个文件头数据结构,然后直接从文件中读取100个字节即可,另外文件头中还包含其他如Bounding box和shape type等结构,我们一次封装即可。

3.1 Bounding Box

Bounding box主要用来表示几何形状边界信息,在文件头中主要是36-99字节使用,由若干double组成,为了后续使用方便,我们封装两种不同类型的Bounding Box结构,具体如下:

class bounding_box4
{
public:
	double x1;
	double y1;
	double x2;
	double y2;
};

class bounding_box2
{
public:
	double x;
	double y;
};

3.2 Shape type

shape type字段主要是用来表示当前文件所描述的几何类型,在文件头中用一个int表示,下面是所有的shape type不同值所表示的几何类型。

ValueShape Type
0Null Shape
1Point
3Polyline
5Polygon
8MultiPoint
11PointZ
13PolyLineZ
15PolygonZ
18MultiPointZ
21PointM
23PolyLineM
25PolygonM
28MultiPointM
31MultiPatch

我们可以用enum class来封装所有的shape type值。

enum class ShapeType
{
	ST_NULL = 0,
	ST_POINT = 1,
	ST_POLYLINE = 3,
	ST_POLYGON = 5,
	ST_MULTI_POINT = 8,
	ST_POINT_Z = 11,
	ST_POLYLINE_Z = 13,
	ST_POLYGON_Z = 15,
	ST_MULTI_POINT_Z = 18,
	ST_POINT_M = 21,
	ST_POLYLINE_M = 23,
	ST_POLYGON_M = 25,
	ST_MULTI_POINT_M = 28,
	ST_MULTI_PATCH = 31,
};

3.3 ShapeFileHeader

我们用ShapeFileHeader类来表示整个文件头部分,这里需要注意文件头中有int和double数据类型,要注意字节对齐引入的整个文件头大小变化问题,这里我们使用pack指令强制4字节对齐,具体如下:

#pragma pack(4)
class ShapeFileHeader
{
public:
	int file_code;
	char reversed[20];
	int file_length;
	int version;
	ShapeType shape_type;
	bounding_box4 xy_bounding;
	bounding_box2 z_boudning;
	bounding_box2 m_boundnig;
};
#pragma pack()

3.4 大小端转换

因为文件头中的有些字段是用大端模式表示的,所以这里我们添加一个转换方法:

void inline swap_bytes32(unsigned int &val)
{
	val = (val >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0xff00) << 8) | (val << 24);
}

测试代码

#include <iostream>
#include <fstream>

using namespace std;

class bounding_box4
{
public:
	double x1;
	double y1;
	double x2;
	double y2;
};

class bounding_box2
{
public:
	double x;
	double y;
};

enum class ShapeType
{
	ST_NULL = 0,
	ST_POINT = 1,
	ST_POLYLINE = 3,
	ST_POLYGON = 5,
	ST_MULTI_POINT = 8,
	ST_POINT_Z = 11,
	ST_POLYLINE_Z = 13,
	ST_POLYGON_Z = 15,
	ST_MULTI_POINT_Z = 18,
	ST_POINT_M = 21,
	ST_POLYLINE_M = 23,
	ST_POLYGON_M = 25,
	ST_MULTI_POINT_M = 28,
	ST_MULTI_PATCH = 31,
};

#pragma pack(4)
class ShapeFileHeader
{
public:
	unsigned int file_code;
	char reversed[20];
	unsigned int file_length;
	unsigned int version;
	ShapeType shape_type;
	bounding_box4 xy_bounding;
	bounding_box2 z_boudning;
	bounding_box2 m_boundnig;
};
#pragma pack()

void inline swap_bytes32(unsigned int& val)
{
	val = (val >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0xff00) << 8) | (val << 24);
}

int main(int argc, char* argv[])
{
	string file_path = "C:\\Users\\Administrator\\Downloads\\AM_RunwayElement.shp";
	ShapeFileHeader header;
	ifstream in(file_path, ifstream::binary);

	in.read((char*)&header, sizeof(header));

	swap_bytes32(header.file_code);
	swap_bytes32(header.file_length);

	// get actual file length
	header.file_length *= 2;

	cout << header.file_code << endl;
	cout << header.version << endl;

	in.close();
}

标签:文件,读取,val,POINT,Shapefile,double,ST,int,bounding
来源: https://blog.csdn.net/weixin_46381545/article/details/116393047