1. GDAL矢量数据读写概述GDALGeospatial Data Abstraction Library作为地理空间数据处理领域的瑞士军刀其矢量数据处理能力在GIS开发中占据核心地位。不同于栅格数据处理GDAL的矢量数据读写通过OGR组件实现从GDAL 2.0起已完全整合。我曾在一个省级国土调查项目中处理过包含200图层的SHP数据深刻体会到掌握GDAL矢量操作对提升空间数据处理效率的价值。矢量数据模型的核心要素包括几何对象点、线、面等OGC标准几何类型属性表与几何对象关联的表格数据空间参考定义坐标系统的投影信息GDAL支持多达80种矢量格式包括通用格式Shapefile、GeoJSON、GML数据库格式PostGIS、FileGDBWeb格式WFS、GeoRSS专业格式CAD、GPS轨迹等2. 核心API与数据模型2.1 驱动注册机制from osgeo import ogr ogr.RegisterAll() # 注册所有驱动 print(可用驱动:, [ogr.GetDriver(i).GetName() for i in range(ogr.GetDriverCount())])典型输出可用驱动: [ESRI Shapefile, MapInfo File, GeoJSON, GML, PostgreSQL...]2.2 数据源操作数据源DataSource是GDAL中的顶级容器对应单个文件或数据库连接# 打开现有数据源 ds ogr.Open(data.shp, 0) # 0表示只读 if ds is None: raise RuntimeError(文件打开失败) # 创建新数据源 driver ogr.GetDriverByName(ESRI Shapefile) if os.path.exists(output.shp): driver.DeleteDataSource(output.shp) # Shapefile需先删除旧文件 new_ds driver.CreateDataSource(output.shp)2.3 图层操作图层Layer是数据源中的逻辑分组相当于GIS中的专题图层# 获取图层 layer ds.GetLayer(0) # 按索引获取 layer ds.GetLayerByName(roads) # 按名称获取 # 创建新图层 srs ogr.osr.SpatialReference() srs.ImportFromEPSG(4326) # WGS84坐标系 new_layer new_ds.CreateLayer( buildings, srs, ogr.wkbPolygon # 几何类型 )2.4 字段定义属性字段需在创建要素前定义# 添加字段 field_defn ogr.FieldDefn(name, ogr.OFTString) field_defn.SetWidth(50) # 字符串长度限制 new_layer.CreateField(field_defn) # 字段类型包括 # OFTInteger, OFTReal, OFTString, OFTDate等3. 读写操作实战3.1 要素读取layer.ResetReading() # 重置读取位置 for feature in layer: geom feature.GetGeometryRef() print(几何类型:, geom.GetGeometryName()) print(坐标:, geom.ExportToWkt()) # 获取属性 print(属性:, feature.GetField(name)) # 空间过滤 if geom.Contains(other_geom): process_selected_feature(feature)3.2 要素写入# 创建要素模板 feature_defn new_layer.GetLayerDefn() feature ogr.Feature(feature_defn) # 设置几何 wkt POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0)) geom ogr.CreateGeometryFromWkt(wkt) feature.SetGeometry(geom) # 设置属性 feature.SetField(name, 示例地块) # 提交到图层 new_layer.CreateFeature(feature) feature None # 释放资源3.3 批量操作优化处理大规模数据时需注意# 开启事务支持的事务类型取决于驱动 if new_ds.TestCapability(ogr.ODsCTransactions): new_ds.StartTransaction() try: for i in range(10000): # 批量创建要素... if i % 1000 0: # 定期提交 new_ds.CommitTransaction() new_ds.StartTransaction() new_ds.CommitTransaction() except: new_ds.RollbackTransaction()4. 高级应用技巧4.1 坐标系转换source_srs layer.GetSpatialRef() target_srs ogr.osr.SpatialReference() target_srs.ImportFromEPSG(3857) # Web墨卡托 coord_trans ogr.osr.CoordinateTransformation( source_srs, target_srs ) feature.GetGeometryRef().Transform(coord_trans)4.2 几何操作# 缓冲区分析 buffer geom.Buffer(0.01) # 0.01度缓冲 # 空间关系判断 if geom1.Intersects(geom2): overlap geom1.Intersection(geom2) # 简化几何 simplified geom.SimplifyPreserveTopology(0.001)4.3 属性过滤# SQL查询 sql SELECT * FROM roads WHERE speed_limit 60 results ds.ExecuteSQL(sql) # 属性过滤 layer.SetAttributeFilter(population 100000) layer.SetSpatialFilter(bbox_geom) # 空间过滤5. 性能优化与问题排查5.1 性能优化空间索引对大型Shapefile使用.qix或.sbn索引ogrinfo -sql CREATE SPATIAL INDEX ON roads roads.shp批量操作使用事务提升写入性能内存缓存对频繁访问的数据使用MEM驱动5.2 常见问题问题1中文属性乱码# 设置编码仅部分驱动支持 layer.SetMetadataItem(ENCODING, GBK)问题2Shapefile文件锁ds None # 必须显式释放才能解除文件锁问题3坐标系缺失if layer.GetSpatialRef() is None: print(警告缺少空间参考)5.3 调试技巧# 打印详细错误信息 gdal.UseExceptions() # 启用异常抛出 try: ds ogr.Open(invalid.shp) except Exception as e: print(GDAL错误:, e.errmsg)6. 实战案例省界数据合并以处理中国省级行政区划数据为例# 合并多个省份Shapefile output_ds driver.CreateDataSource(china_provinces.shp) output_layer output_ds.CreateLayer(...) for province in [jiangsu, zhejiang, shanghai]: ds ogr.Open(f{province}.shp) layer ds.GetLayer(0) for feat in layer: new_feat ogr.Feature(output_layer.GetLayerDefn()) new_feat.SetGeometry(feat.GetGeometryRef().Clone()) new_feat.SetField(name, feat.GetField(NAME)) output_layer.CreateFeature(new_feat) ds None # 生成空间索引 output_ds.ExecuteSQL(CREATE SPATIAL INDEX ON china_provinces)在最近参与的自然资源调查项目中这套方法成功将原本需要人工处理3天的工作压缩到15分钟完成。特别是GDAL的空间过滤功能在处理跨省界地块时展现出极高效率。