用 NetTopologySuite 读取 .shp 文件最稳妥
直接手写解析 Shapefile 是不现实的——它由
.shp、
.shx、
.dbf三个二进制/混合格式文件组成,且坐标系、几何类型、字段编码(如 GBK/UTF-8)都需手动处理。目前 C# 生态中,
NetTopologySuite配合
NetTopologySuite.IO.ShapeFile是最成熟、维护活跃的选择,支持读取点/线/面及属性,也兼容常见投影(如 WGS84、Web Mercator)。
安装方式:
dotnet add package NetTopologySuite
dotnet add package NetTopologySuite.IO.ShapeFile
读取时必须同时提供 .shp + .shx + .dbf 三个文件
Shapefile 是“文件集合”,缺一不可:
.shp存几何,
.shx是索引(加速随机访问),
.dbf存属性表。只传
.shp路径会抛
System.IO.FileNotFoundException或静默跳过属性。 确保三个文件同名同目录,例如:
roads.shp、
roads.shx、
roads.dbf路径传入时只需指定
.shp文件名,库会自动拼出其他两个:
new ShapefileDataReader(@"C:\data\roads.shp")如果
.dbf编码不是默认 ANSI(如中文环境常用 GBK),需显式指定:
new ShapefileDataReader(path, new DbfColumnDescriptor { Encoding = Encoding.GetEncoding("GBK") })
Geometry 类型和坐标顺序容易反
Shapefile 规范中,坐标是
(X, Y)即
(经度, 纬度),但很多 GIS 工具(包括部分 QGIS 导出)可能误存为
(Y, X)。NetTopologySuite 默认按规范解析,若发现多边形方向错乱、点明显偏移,优先检查原始数据坐标顺序。 读出的
Geometry对象,其
Coordinate数组第一个是
X,第二个是
Y;不要直接当成
Latitude, Longitude去用 用
geometry.Coordinates[0].X取经度,
geometry.Coordinates[0].Y取纬度 若确认源数据是
(lat, lng)存储,需在读取后批量交换:
coord.X ↔ coord.Y
没有内置坐标系转换,WKT/Proj 字符串得自己配
ShapefileDataReader会尝试从
.prj文件读 EPSG 或 WKT,但不自动做坐标变换。如果你拿到的是 UTM 坐标或地方坐标系,而需要转 WGS84 经纬度,必须额外引入
ProjNet4GeoAPI或调用外部 PROJ 库。
常见情况:
.prj内容是
PROJCS["CGCS2000_3_Degree_GK_Zone_35", ...],此时
reader.Projection会返回 WKT 字符串,但不会自动转点——你得用
ProjNet构建
CoordinateTransformation实例再逐点转换。
真正麻烦的不是读取,而是确认原始数据到底用什么坐标系、有没有
.prj、
.prj是否准确——这三个问题比代码本身更常卡住进度。
