记录使用geotools工具,实现shp和geojson数据互转
爬坑:不使用依赖:vividsolutions ,因为 1.8 与 geotools 20以后版本jts 不一致,会报错。
<dependency>
<groupId>com.vividsolutions</groupId>
<artifactId>jts</artifactId>
<version>1.8</version>
<type>pom</type>
</dependency>
----------------------------------------------------------开启编码-------------------------------------------------------
1. 引起pom依赖jar
<dependencies> <dependency> <groupId>org.geotools</groupId> <artifactId>gt-shapefile</artifactId> <version>20.3</version> </dependency> <dependency> <groupId>org.geotools</groupId> <artifactId>gt-api</artifactId> <version>20.3</version> </dependency> <dependency> <groupId>org.geotools</groupId> <artifactId>gt-geojson</artifactId> <version>20.3</version> </dependency> <dependency> <groupId>org.geotools</groupId> <artifactId>gt-geometry</artifactId> <version>20.3</version> </dependency> <dependency> <groupId>org.geotools</groupId> <artifactId>gt-jts-wrapper</artifactId> <version>20.3</version> </dependency> <dependency> <groupId>org.geotools</groupId> <artifactId>gt-main</artifactId> <version>20.3</version> </dependency> <dependency> <groupId>org.geotools</groupId> <artifactId>gt-epsg-hsql</artifactId> <version>20.3</version> </dependency> <dependency> <groupId>org.geotools</groupId> <artifactId>gt-opengis</artifactId> <version>20.3</version> </dependency> <dependency> <groupId>org.geotools</groupId> <artifactId>gt-data</artifactId> <version>20.3</version> </dependency> <dependency> <groupId>org.geotools</groupId> <artifactId>gt-referencing</artifactId> <version>20.3</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.83</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.0</version> <configuration> <source>1.8</source> <target>1.8</target> <skip>true</skip> </configuration> </plugin> </plugins> </build>
2. 上代码,自动识别坐标系,默认为84坐标
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.geotools.referencing.CRS;
import org.locationtech.jts.geom.*;
import org.geotools.data.FeatureWriter;
import org.geotools.data.Transaction;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geojson.feature.FeatureJSON;
import org.geotools.geojson.geom.GeometryJSON;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import java.io.*;
import java.nio.charset.Charset;
import java.util.*;
/**
* @author qiaobing1226
* @since 2022/10/28 上午10:52
* 参考:https://blog.csdn.net/qiaobing1226/article/details/127612665
*/
public class Shp2GeojsonUtils {
private static final String POINT = "Point";
private static final String MULTIPOINT = "MultiPoint";
private static final String LINESTRING = "LineString";
private static final String MULTILINESTRING = "MultiLineString";
private static final String POLYGON = "Polygon";
private static final String MULTIPOLYGON = "MultiPolygon";
private static final String THE_GEOM = "the_geom";
private static final String PROPERTIES = "properties";
private static final String GEOMETRY = "geometry";
private static final String GBK = "GBK";
/**
* geoJson转换为shp文件
*
* @param jsonPath
* @param shpPath
* @return
*/
public static Map<String, Object> geoJson2Shape(String jsonPath, String shpPath) {
Map<String, Object> map = new HashMap<>();
GeometryJSON geoJson = new GeometryJSON();
try {
JSONObject json = readGeoJsonFile(jsonPath);
JSONArray features = (JSONArray) json.get("features");
JSONObject feature0 = JSONObject.parseObject(features.get(0).toString());
// 获取属性名称
Set properties = JSONObject.parseObject(feature0.getString(PROPERTIES)).keySet();
String strType = ((JSONObject) feature0.get(GEOMETRY)).getString("type");
String strCrs = json.getJSONObject("crs").getJSONObject(PROPERTIES).getString("name");
CoordinateReferenceSystem crs = CRS.decode(strCrs);
ShapefileDataStore shapefileDataStore = dataStore(properties, strType, shpPath, crs);
if (shapefileDataStore == null) {
return map;
}
// 设置Writer
FeatureWriter<SimpleFeatureType, SimpleFeature> writer = shapefileDataStore.getFeatureWriter(shapefileDataStore.getTypeNames()[0],
Transaction.AUTO_COMMIT);
for (int i = 0, len = features.size(); i < len; i++) {
String strFeature = features.get(i).toString();
Reader reader = new StringReader(strFeature);
SimpleFeature feature = writer.next();
switch (strType) {
case POINT:
feature.setAttribute(THE_GEOM, geoJson.readPoint(reader));
break;
case MULTIPOINT:
feature.setAttribute(THE_GEOM, geoJson.readMultiPoint(reader));
break;
case LINESTRING:
feature.setAttribute(THE_GEOM, geoJson.readLine(reader));
break;
case MULTILINESTRING:
feature.setAttribute(THE_GEOM, geoJson.readMultiLine(reader));
break;
case POLYGON:
feature.setAttribute(THE_GEOM, geoJson.readPolygon(reader));
break;
case MULTIPOLYGON:
feature.setAttribute(THE_GEOM, geoJson.readMultiPolygon(reader));
break;
}
Iterator iterator = properties.iterator();
while (iterator.hasNext()) {
String str = iterator.next().toString();
JSONObject element = JSONObject.parseObject(features.get(i).toString());
feature.setAttribute(str, JSONObject.parseObject(element.getString(PROPERTIES)).get(str));
}
writer.write();
}
writer.close();
shapefileDataStore.dispose();
map.put("status", 200);
map.put("message", "shp转换success");
} catch (Exception e) {
map.put("status", 400);
map.put("message", e.getMessage());
e.printStackTrace();
}
return map;
}
/**
* 读取geojosn文件
*
* @param jsonPath
* @return
*/
private static JSONObject readGeoJsonFile(String jsonPath) {
// 读文件到Stringbuffer
StringBuffer sb = new StringBuffer();
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(jsonPath));
String str;
while ((str = br.readLine()) != null) {// 逐行读取
sb.append(str + "\r\n");
}
br.close();
} catch (Exception e) {
if (br != null) {
try {
br.close();
} catch (Exception exception) {
exception.printStackTrace();
}
}
e.printStackTrace();
}
return JSONObject.parseObject(sb.toString());
}
/**
* 设置shp文件属性
*
* @param properties
* @param strType
* @param shpPath
* @return
*/
private static ShapefileDataStore dataStore(Set properties, String strType, String shpPath, CoordinateReferenceSystem crs) {
try {
Class<?> geoType = null;
switch (strType) {
case POINT:
geoType = Point.class;
break;
case MULTIPOINT:
geoType = MultiPoint.class;
break;
case LINESTRING:
geoType = LineString.class;
break;
case MULTILINESTRING:
geoType = MultiLineString.class;
break;
case POLYGON:
geoType = Polygon.class;
break;
case MULTIPOLYGON:
geoType = MultiPolygon.class;
break;
}
// 创建shape文件对象
File file = new File(shpPath);
Map<String, Serializable> params = new HashMap<String, Serializable>();
params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL());
ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);
// 定义图形信息和属性信息
SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
//默认84坐标
tb.setCRS(crs == null ? DefaultGeographicCRS.WGS84 : crs);
tb.setName("shapefile");
// 类型,Point/MultiPoint/LineString/MultiLineString/Polygon/MultiPolygon
tb.add("the_geom", geoType);
Iterator propertiesIter = properties.iterator();
// 设置属性
while (propertiesIter.hasNext()) {
String str = propertiesIter.next().toString();
// 此处设置为string
tb.add(str, String.class);
}
ds.createSchema(tb.buildFeatureType());
// 设置编码
Charset charset = Charset.forName(GBK);
ds.setCharset(charset);
return ds;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
/**
* shp文件转换geojson数据
*
* @param shpPath
* @return
*/
public static Map<String, Object> shp2Geojson(String shpPath, String jsonPath) {
Map<String, Object> map = new HashMap();
//新建json对象
JSONObject geojsonObject = new JSONObject();
geojsonObject.put("type", "FeatureCollection");
try {
JSONArray array = new JSONArray();
String fileName = readShpContent(shpPath, array);
geojsonObject.put("features", array);
geojsonObject.put("name", fileName);
String crs = getCoordinateSystemWKT(shpPath);
//GEOGCS表示这个是地址坐标系,PROJCS则表示是平面投影坐标系
JSONObject crsJson = new JSONObject();
JSONObject proJson = new JSONObject();
crsJson.put("type", "name");
if (crs.startsWith("PROJCS")) {
proJson.put("name", "urn:ogc:def:crs:EPSG::3857");
crsJson.put("properties", proJson);
} else {
proJson.put("name", "urn:ogc:def:crs:OGC:1.3:CRS84");
crsJson.put("properties", proJson);
}
geojsonObject.put("crs", crsJson);
// itertor.close();
long startTime = System.currentTimeMillis();
//将json字符串使用字符流写入文件
/* File outputfile=new File(jsonPath);
BufferedWriter bufferedWriter=new BufferedWriter(new FileWriter(outputfile));
bufferedWriter.write(JSON.toJSONString(geojsonObject));
bufferedWriter.flush();
bufferedWriter.close();*/
File outputfile = new File(jsonPath);
FileOutputStream fileOutputStream = new FileOutputStream(outputfile);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "utf-8");
outputStreamWriter.write(JSON.toJSONString(geojsonObject));
outputStreamWriter.flush();
outputStreamWriter.close();
//将json字符串使用字节流写入文件
/* File outputfile=new File(jsonPath);
BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(new FileOutputStream(outputfile));
byte[] bytes= JSON.toJSONString(geojsonObject).getBytes("utf-8");
bufferedOutputStream.write(bytes);
//fileOutputStream.write(JSON.toJSONString(geojsonObject));
bufferedOutputStream.flush();
bufferedOutputStream.close();*/
// long endTime=System.currentTimeMillis();
// System.out.println("当前程序耗时:"+(endTime-startTime)+"ms");
} catch (Exception e) {
map.put("status", "failure");
map.put("message", e.getMessage());
e.printStackTrace();
}
//
return geojsonObject;
}
private static String readShpContent(String shpPath, JSONArray array) {
String fileName = "";
try {
FeatureJSON fjson = new FeatureJSON();
//获取featurecollection
File file = new File(shpPath);
ShapefileDataStore shpDataStore = null;
shpDataStore = new ShapefileDataStore(file.toURL());
//设置编码
/* Charset charset = Charset.forName("GBK");
shpDataStore.setCharset(charset);*/
fileName = shpDataStore.getTypeNames()[0];
SimpleFeatureSource featureSource = null;
featureSource = shpDataStore.getFeatureSource(fileName);
SimpleFeatureCollection result = featureSource.getFeatures();
SimpleFeatureIterator itertor = result.features();
//遍历feature转为json对象
while (itertor.hasNext()) {
SimpleFeature feature = itertor.next();
StringWriter writer = new StringWriter();
fjson.writeFeature(feature, writer);
String temp = writer.toString();
Object geometry = JSONObject.parseObject(temp).getString(GEOMETRY);
byte[] b = temp.getBytes("iso8859-1");
temp = new String(b, GBK);
JSONObject json = JSON.parseObject(temp);
array.add(json);
}
itertor.close();
} catch (Exception e) {
e.printStackTrace();
}
return fileName;
}
/**
* 获取Shape文件的坐标系信息,GEOGCS表示这个是地址坐标系,PROJCS则表示是平面投影坐标系
*
* @shpPath
*/
public static String getCoordinateSystemWKT(String shpPath) {
ShapefileDataStoreFactory factory = new ShapefileDataStoreFactory();
ShapefileDataStore dataStore = null;
try {
dataStore = (ShapefileDataStore) factory.createDataStore(new File(shpPath).toURI().toURL());
return dataStore.getSchema().getCoordinateReferenceSystem().toWKT();
} catch (UnsupportedOperationException | IOException e) {
e.printStackTrace();
} finally {
dataStore.dispose();
}
return "";
}
/**
* 工具类测试方法
*
* @param args
*/
public static void main(String[] args) throws Exception {
Shp2GeojsonUtils shpToGeojson = new Shp2GeojsonUtils();
// // shape2Geojson
String shpPath = "/Users/ecarx/Desktop/geojson/上下高架mct/123/AD_Road.shp";
String jsonPath = "/Users/ecarx/Desktop/geojson/AD_Road.geojson";
Map<String, Object> map = shpToGeojson.shp2Geojson(shpPath, jsonPath);
// geojson2Shape
// String shpPath = "/Users/ecarx/Desktop/geojson/上下高架mct/123/AD_Road.shp";
// String jsonPath = "/Users/ecarx/Desktop/geojson/上下高架mct/AD_Road.geojson";
// Map<String, Object> map = shpToGeojson.geoJson2Shape(jsonPath, shpPath);
// System.out.println(map.toString());
}
}