使用GeoTools解析shp文件内容
前言
记录一下工作中使用GeoTools解析shp过程。
默认上传shp文件为zip格式文件,shp压缩包内容如下图
代码流程
1.解压zip文件
// 解压缩zip包
File shpFile = ShpParseUtil.unShapeZip(file.getInputStream(), tempDir);
2.解析shp文件内容
parseShapeFile(shpFile);
public static void parseShapeFile(File file) throws Exception {
Map<String, Object> map = new HashMap<>(1);
map.put("url", file.toURI().toURL());
DataStore dataStore = DataStoreFinder.getDataStore(map);
//字符转码,防止中文乱码
ShapefileDataStore shpStore = (ShapefileDataStore) dataStore;
// shpStore.setCharset(StandardCharsets.UTF_8);
shpStore.setCharset(Charset.forName("GBK"));
SimpleFeatureSource source = shpStore.getFeatureSource();
SimpleFeatureType schema = source.getSchema();
Query query = new Query(schema.getTypeName());
FeatureCollection<SimpleFeatureType, SimpleFeature> collection = source.getFeatures(query);
//获取shp文件内容
try (FeatureIterator<SimpleFeature> features = collection.features()) {
while (features.hasNext()) {
SimpleFeature feature = features.next();
String name = feature.getName().toString();
System.out.println("名称:" + name);
//获取坐标系
CoordinateReferenceSystem coordinateReferenceSystem = feature.getFeatureType().getCoordinateReferenceSystem();
if (coordinateReferenceSystem != null) {
ReferenceIdentifier referenceIdentifier = coordinateReferenceSystem.getCoordinateSystem().getName();
String code = referenceIdentifier.getCode();
System.out.println("坐标系:" + code);
}
//获取shp文件的属性信息
// List<Object> attributes = feature.getAttributes();
String geomType = feature.getFeatureType().getDescriptor("the_geom").getType().getName().toString();
System.out.println("属性值数量:" + feature.getValue().size());
Map<String, Object> propertoryMap = feature.getValue().stream()
.filter(property -> !"the_geom".equals(property.getName().toString()))
.collect(Collectors.toMap(property -> property.getName().toString(), Property::getValue));
for (Property property : feature.getValue()) {
String propertyName = property.getName().toString();
String typeName = property.getType().getName().toString();
System.out.println("属性名:" + propertyName + "类型:" + typeName + " 属性值:" + property.getValue());
}
Geometry geom = (Geometry) feature.getAttribute("the_geom");
String geometryType = geom.getGeometryType();
// 封装为geojson格式
String geoJson = convertToJson(geom,propertoryMap);
}
}
}
工具类
public class ShpParseUtil {
/**
* 解压shapefile压缩包
*/
public static File unShapeZip(InputStream inputStream,File tempDir){
// 解压shp文件
File unzipFiles = ZipUtil.unzip(inputStream, tempDir, null);
Optional<File> optional = ListUtil.toList(unzipFiles.listFiles())
.stream()
.filter(file1 -> file1.getName().endsWith(".shp"))
.findAny();
if (!optional.isPresent()) {
throw new JeecgBootException("不存在解压后shp文件");
}
return optional.get();
}
/**
* 格式化矢量数据为json格式
* @param the_geom
* @return
*/
public static String convertToJson(Geometry the_geom, Map<String, Object> propertoryMap){
String geomType = the_geom.getGeometryType();
// 解析组装坐标Json数组
JSONArray geoJsonArray = getCoordinates(the_geom);
// 构建 GeoJSON 对象
JSONObject geoJsonFeature = new JSONObject();
geoJsonFeature.put("type", "Feature");
JSONObject geometry = new JSONObject();
geometry.put("type", geomType);
geometry.put("coordinates", geoJsonArray);
geoJsonFeature.put("geometry", geometry);
// 添加属性
geoJsonFeature.put("properties", propertoryMap);
// 返回 GeoJSON 结果
JSONObject geoJson = new JSONObject();
geoJson.put("type", "FeatureCollection");
geoJson.put("features", new JSONArray().fluentAdd(geoJsonFeature));
return geoJson.toString();
}
/**
* 解析不同类型坐标返回JSON数组
*/
private static JSONArray getCoordinates(Geometry geometry) {
if (geometry instanceof Point) {
Point point = (Point) geometry;
JSONArray geoJsonPoints = new JSONArray();
geoJsonPoints.add(point.getX());
geoJsonPoints.add(point.getY());
return geoJsonPoints;
} else if (geometry instanceof LineString) {
LineString lineString = (LineString) geometry;
org.locationtech.jts.geom.Coordinate[] coordinates = lineString.getCoordinates();
JSONArray geoJsonLineString = new JSONArray();
for (Coordinate coordinate : coordinates) {
geoJsonLineString.add(coordinate.getX());
geoJsonLineString.add(coordinate.getY());
}
return geoJsonLineString;
} else if (geometry instanceof Polygon) {
Polygon polygon = (Polygon) geometry;
return getPolygonCoordinates(polygon);
} else if (geometry instanceof MultiPoint) {
MultiPoint multiPoint = (MultiPoint) geometry;
JSONArray coords = new JSONArray();
for (int i = 0; i < multiPoint.getNumGeometries(); i++) {
Point point = (Point) multiPoint.getGeometryN(i);
coords.add(new JSONArray().fluentAdd(point.getX()).fluentAdd(point.getY()));
}
return coords;
} else if (geometry instanceof MultiLineString) {
MultiLineString multiLineString = (MultiLineString) geometry;
JSONArray coords = new JSONArray();
for (int i = 0; i < multiLineString.getNumGeometries(); i++) {
coords.add(getCoordinates(multiLineString.getGeometryN(i)));
}
return coords;
} else if (geometry instanceof MultiPolygon) {
MultiPolygon multiPolygon = (MultiPolygon) geometry;
JSONArray coords = new JSONArray();
for (int i = 0; i < multiPolygon.getNumGeometries(); i++) {
coords.add(getPolygonCoordinates((Polygon) multiPolygon.getGeometryN(i)));
}
return coords;
} else {
return null;
}
}
// 解析获取多边形的坐标数组
private static JSONArray getPolygonCoordinates(Polygon polygon) {
JSONArray coords = new JSONArray();
// 多边形外环
JSONArray exteriorRing = new JSONArray();
for (int i = 0; i < polygon.getExteriorRing().getNumPoints(); i++) {
exteriorRing.fluentAdd(new JSONArray().fluentAdd(polygon.getExteriorRing().getCoordinateN(i).x)
.fluentAdd(polygon.getExteriorRing().getCoordinateN(i).y));
}
coords.add(exteriorRing);
// 多边形内环
for (int i = 0; i < polygon.getNumInteriorRing(); i++) {
JSONArray interiorRing = new JSONArray();
for (int j = 0; j < polygon.getInteriorRingN(i).getNumPoints(); j++) {
interiorRing.fluentAdd(new JSONArray().fluentAdd(polygon.getInteriorRingN(i).getCoordinateN(j).x)
.fluentAdd(polygon.getInteriorRingN(i).getCoordinateN(j).y));
}
coords.add(interiorRing);
}
return coords;
}
}