package org.springblade.common.utils; import cn.hutool.core.io.FileUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.text.CharSequenceUtil; import com.alibaba.fastjson.JSONObject; import org.geotools.data.*; import org.geotools.data.shapefile.ShapefileDataStore; import org.geotools.data.shapefile.ShapefileDataStoreFactory; import org.geotools.feature.FeatureCollection; import org.geotools.feature.FeatureIterator; import org.geotools.feature.simple.SimpleFeatureTypeBuilder; import org.geotools.geojson.feature.FeatureJSON; import org.geotools.referencing.CRS; import org.locationtech.jts.geom.*; import org.locationtech.jts.io.ParseException; import org.locationtech.jts.io.WKTReader; import org.opengis.feature.GeometryAttribute; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.filter.Filter; import org.opengis.referencing.FactoryException; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.springblade.core.log.exception.ServiceException; import java.io.File; import java.io.IOException; import java.io.Serializable; import java.io.StringWriter; import java.nio.charset.StandardCharsets; import java.util.*; public class ShapeFileUtil { /** * 导出shp文件 * * @param dataPropertiesList 属性列表{属性名:属性值} * @param fileName 导出shp文件名 * @param geomType geometry类型 * @param saveFolder 导出位置 */ public static void exportShp(List> dataPropertiesList, String fileName, String geomType, String saveFolder) { String path = saveFolder + "/" + fileName; //创建保存shp文件夹 File dir = new File(path); if (!dir.exists()) { FileUtil.mkdir(dir); } //shp文件路径 String shpFileName = fileName + ".shp"; String fileUrl = path+ "/" + shpFileName; File file = new File(fileUrl); FeatureWriter writer = null; ShapefileDataStore ds = null; try { Map params = new HashMap<>(); params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL()); ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params); //定义图形信息和属性信息 SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder(); //设置坐标系 CoordinateReferenceSystem crs84 = CRS.decode("EPSG:4326", true); tb.setCRS(crs84); //设置文件名 tb.setName(fileName); //定义导出shp文件地块属性名称 String geomProperty = "the_geom"; String idProperty = "ID"; String nameProperty = "name"; //设置图形类型 if ("Polygon".equals(geomType)) { tb.add(geomProperty, Polygon.class); } else if ("MultiPolygon".equals(geomType)) { tb.add(geomProperty, MultiPolygon.class); } else if ("Point".equals(geomType)) { tb.add(geomProperty, Point.class); } else if ("MultiPoint".equals(geomType)) { tb.add(geomProperty, MultiPoint.class); } else if ("LineString".equals(geomType)) { tb.add(geomProperty, LineString.class); } else if ("MultiLineString".equals(geomType)) { tb.add(geomProperty, MultiLineString.class); } else { throw new ServiceException("Geometry中没有该类型:" + geomType); } //设置对应属性类型 tb.add(idProperty, String.class); tb.add(nameProperty, String.class); //设置默认geometry tb.setDefaultGeometry(geomProperty); //创建 ds.createSchema(tb.buildFeatureType()); ds.setCharset(StandardCharsets.UTF_8); //设置Writer writer = ds.getFeatureWriter(ds.getTypeNames()[0], Transaction.AUTO_COMMIT); SimpleFeature feature; for (Map map : dataPropertiesList) { feature = writer.next(); //属性赋值 geometry要赋值wkt格式的 feature.setAttribute(geomProperty, new WKTReader().read((MapUtil.getStr(map, "geometry")))); feature.setAttribute(idProperty, MapUtil.getStr(map, idProperty)); feature.setAttribute(nameProperty, MapUtil.getStr(map, nameProperty)); // String description = MapUtil.getStr(map, "描述"); // if (CharSequenceUtil.isNotBlank(description)) { // feature.setAttribute(descriptionProperty, description); // } } writer.write(); } catch (IOException | FactoryException | ParseException e) { e.printStackTrace(); } finally { //关闭相关流 try { if (writer != null) { writer.close(); } } catch (IOException e) { e.printStackTrace(); } if (ds != null) { ds.dispose(); } } } /** * 导出shp文件 * * @param map 属性列表{属性名:属性值} * @param fileName 导出shp文件名 * @param geomType geometry类型 * @param saveFolder 导出位置 */ public static void exportShp(Map map, String fileName, String geomType, String saveFolder) { String path = saveFolder + "/" + fileName; //创建保存shp文件夹 File dir = new File(path); if (!dir.exists()) { FileUtil.mkdir(dir); } //shp文件路径 String shpFileName = fileName + ".shp"; String fileUrl = path+ "/" + shpFileName; File file = new File(fileUrl); FeatureWriter writer = null; ShapefileDataStore ds = null; try { Map params = new HashMap<>(); params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL()); ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params); //定义图形信息和属性信息 SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder(); //设置坐标系 CoordinateReferenceSystem crs84 = CRS.decode("EPSG:4326", true); tb.setCRS(crs84); //设置文件名 tb.setName(fileName); //定义导出shp文件地块属性名称 String geomProperty = "the_geom"; String idProperty = "ID"; String nameProperty = "name"; //设置图形类型 if ("Polygon".equals(geomType)) { tb.add(geomProperty, Polygon.class); } else if ("MultiPolygon".equals(geomType)) { tb.add(geomProperty, MultiPolygon.class); } else if ("Point".equals(geomType)) { tb.add(geomProperty, Point.class); } else if ("MultiPoint".equals(geomType)) { tb.add(geomProperty, MultiPoint.class); } else if ("LineString".equals(geomType)) { tb.add(geomProperty, LineString.class); } else if ("MultiLineString".equals(geomType)) { tb.add(geomProperty, MultiLineString.class); } else { throw new ServiceException("Geometry中没有该类型:" + geomType); } //设置对应属性类型 tb.add(idProperty, String.class); tb.add(nameProperty, String.class); //设置默认geometry tb.setDefaultGeometry(geomProperty); //创建 ds.createSchema(tb.buildFeatureType()); ds.setCharset(StandardCharsets.UTF_8); //设置Writer writer = ds.getFeatureWriter(ds.getTypeNames()[0], Transaction.AUTO_COMMIT); SimpleFeature feature; feature = writer.next(); //属性赋值 geometry要赋值wkt格式的 feature.setAttribute(geomProperty, new WKTReader().read((MapUtil.getStr(map, "geometry")))); feature.setAttribute(idProperty, MapUtil.getStr(map, idProperty)); feature.setAttribute(nameProperty, MapUtil.getStr(map, nameProperty)); writer.write(); } catch (IOException | FactoryException | ParseException e) { e.printStackTrace(); } finally { //关闭相关流 try { if (writer != null) { writer.close(); } } catch (IOException e) { e.printStackTrace(); } if (ds != null) { ds.dispose(); } } } /** * 将文件解压 * @param zipFile * @return * @throws IOException */ public static FeatureCollection getFeatureCollectionByShpFile(File zipFile) throws IOException { try { String tempDir = FileUtil.getTmpDirPath(); File shapeDir = new File(tempDir + File.separator + new Date().getTime()); shapeDir.mkdir(); List files = ZipUtil.unZipFiles(zipFile, shapeDir.getPath() + File.separator); String shapFileName = ""; for (String fileName : files) { String suffix = fileName.substring(fileName.lastIndexOf(".") + 1); if ("shp".equals(suffix)) { shapFileName = fileName; } } File shapeFile = new File(shapFileName); Map shapeFileParams = new HashMap(); shapeFileParams.put("url", shapeFile.toURI().toURL()); // 设置编码 shapeFileParams.put("charset", "utf-8"); DataStore dataStore = DataStoreFinder.getDataStore(shapeFileParams); if (dataStore == null) { throw new RuntimeException("couldn't load the damn data store: " + shapeFileParams); } String typeName = dataStore.getTypeNames()[0]; FeatureSource source = dataStore.getFeatureSource(typeName); Filter filter = Filter.INCLUDE; FeatureCollection collection = source.getFeatures(filter); return collection; } catch (Exception e) { throw e; } } /** * 解析shp文件返回数据 * @param zipFile: * @return JSONObject * @description 通过shp压缩文件,将其转换为GeoJson格式 */ //将解压后的文件转换成GeoJson格式 public static List> shpToGeoJson(File zipFile) throws IOException{ List> dtoList = new ArrayList<>(); try { FeatureJSON featureJSON = new FeatureJSON(); JSONObject geoJsonObject = new JSONObject(); geoJsonObject.put("type", "FeatureCollection"); // 解压zip文件,获取FeatureCollection FeatureCollection collection = getFeatureCollectionByShpFile(zipFile); // 获取迭代对象 FeatureIterator iterator = collection.features(); // 遍历feature转为json对象 while (iterator.hasNext()) { Map shpDTO = new HashMap<>(); SimpleFeature feature = (SimpleFeature) iterator.next(); StringWriter writer = new StringWriter(); featureJSON.writeFeature(feature, writer); String temp = writer.toString(); JSONObject json = JSONObject.parseObject(temp); Object value = feature.getDefaultGeometryProperty().getValue(); try { // 空间坐标 shpDTO.put("geometry",value); // 空间类型 if (json.getJSONObject("geometry").get("type") != null) { shpDTO.put("type",json.getJSONObject("geometry").getString("type")); } // 名称 if (json.getJSONObject("properties").get("Name")!= null) { shpDTO.put("name",json.getJSONObject("properties").getString("Name")); } // 所属公司名称 if (json.getJSONObject("properties").get("name_1")!= null) { shpDTO.put("firmName",json.getJSONObject("properties").getString("name_1")); } dtoList.add(shpDTO); } catch (NumberFormatException e) { System.err.println("处理单个特征时发生错误:" + e.getMessage()); } catch (Exception e) { System.err.println("处理单个特征时发生错误:" + e.getMessage()); } } iterator.close(); } catch (IOException e) { System.err.println("读取或解析文件时发生错误:" + e.getMessage()); throw e; } return dtoList; } public static void main(String[] args) throws IOException, ParseException { // File file = new File("F:\\test4jdata\\shp\\import\\zrq.zip"); File file = new File("F:\\test4jdata\\shp\\zip\\test.zip"); List> list = shpToGeoJson(file); System.out.println("list = " + list); // 导出shp 文件 // List> propertyList = new ArrayList<>(); // for (int i = 0; i < 3; i++) { // Map map = new HashMap<>(); // map.put("ID", i); // map.put("名称", "test" + i); // map.put("描述", "测试shp导出" + i); // map.put("geometry", "MULTILINESTRING ((114.0888763800001 22.549298400000055, 114.0897166200001 22.54931240800005, 114.09006708000004 22.549318250000056, 114.09104754000009 22.549328150000065))"); // propertyList.add(map); // } // String exportPath = "F:\\test4jdata\\shp\\export\\"; // exportShp(propertyList, "test", "MultiLineString",exportPath); // // 打包成 zip 包,然后导出 // String zipPath = "F:\\test4jdata\\shp\\zip\\test.zip"; // boolean folder = ZipUtil.zipFolder(exportPath, zipPath); // 打包成功后导出 } public static double[] getLongitudeLatitude(Geometry wktPoint) throws ParseException { Geometry geometry = wktPoint; if (geometry instanceof Point) { Point point = (Point) geometry; double longitude = point.getX(); double latitude = point.getY(); return new double[]{longitude, latitude}; } else { throw new IllegalArgumentException("The geometry is not a point."); } } }