当前位置: 首页 > news >正文

如何硬解析 .shp 文件中的几何体,拯救 .dbf、.shx 等文件缺失的 ESRI Shapefile 格式文件

最近遇到一个问题就是 ESRI Shapefile 格式文件中 .dbf 文件损坏,导致 .shp 无法打开,又不能放弃这个数据,所以只能做修复,网上搜了很多方法,结果都失败了,所以用 deepseek 查询应解析的方法,亲测可行(简单多边形),现将方法分享:

ESRI Shapefile 文件组成

1 核心文件

扩展名必选用途
.shp存储几何图形(点、线、面等)
.shx存储几何索引(加速查询)
.dbf存储属性数据(类似表格)
.prj坐标系统定义(如 WGS84)
.cpg字符编码声明(如 UTF-8)
  • 必须同时存在 .shp.shx.dbf 文件才能正常使用。
  • 缺失 .prj 可能导致坐标系统未知。

2 .shp 文件结构(二进制格式)

文件头(Header)

偏移量长度类型描述
04Bint32文件标识码(固定 9994
244Bint32版本号(1000
284Bint32几何类型(见下表)
36-6832Bdouble边界框(xmin, ymin, xmax, ymax)

几何记录(Record)

  • 记录头(8B):
    • int32 记录编号(从 1 开始)
    • int32 记录长度(以 16-bit 字为单位)
  • 记录内容
    • int32 几何类型
    • 几何数据(坐标点等)

Shapefile 几何类型

类型值名称描述
0Null Shape空几何
1Point二维点 [x, y]
3PolyLine多段线
5Polygon多边形(首尾闭合)
8MultiPoint多点集合
11PointZ三维点 [x, y, z, m]

多边形规则

  • 外环:顶点按 逆时针 排列
  • 内环(孔洞):顶点按 顺时针 排列

Python 硬解析只有 .shp 文件的已损坏的 ESRI Shapefile 格式数据(Polygon)

环境和数据准备

安装 gma:pip install gma

本文基于:gma 2.1.7,Python 3.12

本文用到数据:
链接: https://pan.baidu.com/s/1kMlji9xqSsYIVn1cygIewA?pwd=9nc1
提取码: 9nc1

代码

import structdef parse_polygon_shp(shp_path):polygons = []iii = 0with open(shp_path, "rb") as f:# 跳过文件头(100字节)f.read(100)while True:# 读取记录头(8字节:记录号+长度)record_header = f.read(8)if not record_header:break# 解析记录头(大端序)record_num = struct.unpack(">i", record_header[:4])[0]record_len = struct.unpack(">i", record_header[4:8])[0]  # 单位:16-bit words# 读取记录内容(长度:record_len * 2 字节)try:record_data = f.read(record_len * 2)except:breakif len(record_data) < 44:  # 多边形至少需要44字节continue# 解析几何类型(小端序,从记录内容开始)shape_type = struct.unpack("<i", record_data[0:4])[0]if shape_type != 5:  # 仅处理多边形continue# 解析边界框(4个double)bbox = struct.unpack("<4d", record_data[4:36])# 解析环数和点数num_parts = struct.unpack("<i", record_data[36:40])[0]num_points = struct.unpack("<i", record_data[40:44])[0]# 解析环的起始索引(num_parts个int32)parts = []offset = 44parts_data = record_data[offset : offset + 4 * num_parts]parts = list(struct.unpack(f"<{num_parts}i", parts_data))offset += 4 * num_parts# 解析所有点(num_points个xy对)points = []points_data = record_data[offset : offset + 16 * num_points]for i in range(num_points):x = struct.unpack("<d", points_data[16*i : 16*i + 8])[0]y = struct.unpack("<d", points_data[16*i + 8 : 16*i + 16])[0]points.append((x, y))# 保存多边形数据polygons.append({"shape_type": shape_type,"bbox": bbox,"num_parts": num_parts,"num_points": num_points,"parts": parts,"points": points})return polygonsshp_path = "青海省.shp"
res = parse_polygon_shp(shp_path)import pandas as pd
from gma import iofts = []
for data in res:pt = data['points']ft = io.CreateFeature(pt, GeomType = 'Polygon', Projection = 'WGS84')fts.append(ft)ly = io.CreateLayer(fts)
ly.SaveAs("青海省_New.shp")

注意:此方法暂不适合复杂的多边形。如果是复杂多边形需要进一步优化。

http://www.dtcms.com/a/294571.html

相关文章:

  • (Python)类的练习与巩固(图书管理系统扩展)(类与方法的基础教程)(if条件扩展)(动态类型)(Python教程)
  • LLC协议支持哪些类型的帧?它们各自的功能是什么?
  • IAR Embedded Workbench for ARM 8.1 安装教程
  • 深兰科技陈海波:AI企业出海要坚持“区域深耕”与“长期主义”
  • 《设计模式之禅》笔记摘录 - 9.责任链模式
  • 使用Ollama,VLLM,LMDeploy部署大模型
  • 二分查找-162.寻找峰值-力扣(LeetCode)
  • P1040 [NOIP 2003 提高组] 加分二叉树
  • 小米浏览器overflow不能左右滑动
  • spring-cloud概述
  • (Arxiv-2025)OVIS-U1技术报告
  • 想曰加密工具好用吗?本地安全、支持多算法的加密方案详解
  • NTC热敏电阻计算公式
  • 【大模型】Hugging Face常见模型格式详解
  • 【硬件-笔试面试题】硬件/电子工程师,笔试面试题-6,(知识点:二极管,少子多子,扩散/漂移运动)
  • mysql中ROW_NUMBER()、RANK()、DENSE_RANK()用法及区别
  • 在AI深度嵌入企业业务的当下——AI时代的融合数据库
  • 知己知彼:深入剖析跨站脚本(XSS)攻击与防御之道
  • React+Three.js实现3D场景压力/温度/密度分布可视化
  • 使用 piano_transcription_inference将钢琴录音转换为 MIDI
  • 2.4 PNIO-CM
  • 初级网安作业笔记3
  • opencv学习(视频读取)
  • Spring Data Redis 从入门到精通:原理与实战指南
  • 2025暑期—06神经网络-常见网络
  • JVM、Dalvik、ART区别
  • JS逆向实战案例之———x日头条【a-bogus】分析
  • 解析 Chromium 架构分层下 Windows 与 Linux 链接器行为差异及其影响
  • [深度学习] 大模型学习3下-模型训练与微调
  • 提升ARM Cortex-M系统性能的关键技术:TCM技术解析与实战指南