Shapefile与GeoJSON互转工具 - 在线SHP转GeoJSON格式转换器
Shapefile ⇄ GeoJSON 互转工具
在线转换 Shapefile 与 GeoJSON 格式,支持双向转换和点、线、面要素
使用说明
支持 Shapefile 与 GeoJSON 双向转换,上传 .shp、.dbf 等文件自动解析并转换为目标格式。
上传 Shapefile 文件
点击或拖拽文件到此处上传
支持 .shp、.shx、.dbf、.prj、.cpg 格式(必需:.shp 和 .dbf)
格式说明
Shapefile 是由 Esri 开发的地理空间矢量数据格式,广泛应用于 GIS 软件中。一个完整的 Shapefile 由多个文件组成:
- .shp - 存储几何图形(点、线、面)
- .shx - 存储几何图形的索引
- .dbf - 存储属性数据表
- .prj - 存储坐标系统信息(可选)
- .cpg - 存储字符编码信息(可选)
GeoJSON 是一种基于 JSON 的地理空间数据交换格式,易于解析和使用,是现代 Web 地图应用的标准格式。
支持的要素类型
- Point - 点要素(如地标、兴趣点)
- LineString - 线要素(如路径、轨迹)
- Polygon - 面要素(如区域、边界)
- MultiPoint - 多点要素
- MultiLineString - 多线要素
- MultiPolygon - 多面要素
注意事项
- Shapefile 必须同时包含 .shp 和 .dbf 文件才能正确转换
- 转换过程在浏览器本地完成,数据不会上传到服务器
- 大文件(超过 50MB)可能导致浏览器卡顿,建议使用桌面 GIS 软件处理
代码实现
JavaScript
/**
* Shapefile ⇄ GeoJSON 互转
* 需要安装: npm install shpjs @mapbox/shp-write
*/
import getShapefile from 'shpjs';
import shpwrite from '@mapbox/shp-write';
// ==================== Shapefile 转 GeoJSON ====================
/**
* 将单组 Shapefile 文件转换为 GeoJSON
* @param {ArrayBuffer} shpBuffer - .shp 文件内容
* @param {ArrayBuffer} [dbfBuffer] - .dbf 文件内容
* @param {string} [prj] - .prj 文件内容(可选,坐标系信息)
* @param {string} [cpg] - .cpg 文件内容(可选,字符编码)
* @returns {Promise<Object>} GeoJSON FeatureCollection
*/
async function shpToGeoJSON(shpBuffer, dbfBuffer, prj, cpg) {
return await getShapefile({ shp: shpBuffer, dbf: dbfBuffer, prj, cpg });
}
/**
* 将多组 Shapefile 文件合并转换为单个 GeoJSON
* @param {Array<{shp: ArrayBuffer, dbf?: ArrayBuffer, prj?: string, cpg?: string}>} groups
* @returns {Promise<Object>} 合并后的 GeoJSON FeatureCollection
*/
async function batchShpToGeoJSON(groups) {
const allFeatures = [];
for (const g of groups) {
const geojson = await shpToGeoJSON(g.shp, g.dbf, g.prj, g.cpg);
if (geojson.features) allFeatures.push(...geojson.features);
else if (geojson.type === 'Feature') allFeatures.push(geojson);
}
return { type: 'FeatureCollection', features: allFeatures };
}
// ==================== GeoJSON 转 Shapefile ====================
/**
* 将 Multi* 几何类型展平为基本类型
* @param {Object} geojson - GeoJSON FeatureCollection
* @returns {Object} 展平后的 GeoJSON
*/
function flattenMultiGeometry(geojson) {
const features = [];
for (const feature of geojson.features) {
const geom = feature.geometry;
if (!geom) continue;
const multiMap = { MultiPoint: 'Point', MultiLineString: 'LineString', MultiPolygon: 'Polygon' };
if (multiMap[geom.type]) {
for (const coords of geom.coordinates) {
features.push({ ...feature, geometry: { type: multiMap[geom.type], coordinates: coords } });
}
} else {
features.push(feature);
}
}
return { type: 'FeatureCollection', features };
}
/**
* 将 GeoJSON 转换为 Shapefile 并下载
* @param {Object} geojson - GeoJSON FeatureCollection
* @param {string} [filename] - 下载文件名(不含扩展名)
*/
function geoJSONToShp(geojson, filename = 'shapefile') {
// 展平 Multi* 类型
const flattened = flattenMultiGeometry(geojson);
// @mapbox/shp-write 自动按几何类型拆分为不同图层
const base64 = shpwrite.zip(flattened, {
folder: filename,
types: { point: 'points', polyline: 'lines', polygon: 'polygons' }
});
// base64 转 Blob 下载
const bytes = atob(base64);
const buffer = new Uint8Array(bytes.length);
for (let i = 0; i < bytes.length; i++) buffer[i] = bytes.charCodeAt(i);
const blob = new Blob([buffer], { type: 'application/zip' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename + '.zip';
a.click();
URL.revokeObjectURL(url);
}
// ==================== 使用示例 ====================
// Shapefile 转 GeoJSON
const shpFile = await fetch('data.shp').then(r => r.arrayBuffer());
const dbfFile = await fetch('data.dbf').then(r => r.arrayBuffer());
const result = await shpToGeoJSON(shpFile, dbfFile);
console.log(`要素数量: ${result.features.length}`);
// GeoJSON 转 Shapefile
geoJSONToShp(result, 'output');
Java
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.geojson.feature.FeatureJSON;
import org.geotools.data.simple.SimpleFeatureCollection;
import java.io.*;
/**
* Shapefile 转 GeoJSON 工具类
* 依赖: GeoTools (Maven: org.geotools:gt-shapefile, org.geotools:gt-geojson)
*/
public class ShpToGeoJSON {
/**
* 转换 Shapefile 为 GeoJSON
* @param shpFile Shapefile 文件
* @return GeoJSON 字符串
*/
public static String convert(File shpFile) throws Exception {
ShapefileDataStore store = new ShapefileDataStore(shpFile.toURI().toURL());
SimpleFeatureCollection features = store.getFeatureSource().getFeatures();
StringWriter writer = new StringWriter();
new FeatureJSON().writeFeatureCollection(features, writer);
store.dispose();
return writer.toString();
}
public static void main(String[] args) throws Exception {
File shpFile = new File("data.shp");
String geoJSON = convert(shpFile);
System.out.println("GeoJSON: " + geoJSON);
}
}Python
import geopandas as gpd
import json
def shp_to_geojson(shp_path: str, output_path: str = None) -> dict:
"""
Shapefile 转 GeoJSON
Args:
shp_path: Shapefile 文件路径
output_path: 输出 GeoJSON 文件路径(可选)
Returns:
GeoJSON 字典对象
"""
# 读取 Shapefile
gdf = gpd.read_file(shp_path)
# 转换为 GeoJSON
geojson = json.loads(gdf.to_json())
# 保存到文件(可选)
if output_path:
gdf.to_file(output_path, driver='GeoJSON')
return geojson
# 使用示例
if __name__ == '__main__':
result = shp_to_geojson('data.shp', 'output.geojson')
print(f"要素数量: {len(result['features'])}")
print(json.dumps(result, indent=2, ensure_ascii=False))