#8.16shp与geojson互转
在线转换工具:https://mapshaper.org/
桌面工具idesktop
/*
* 数据结构:
* FeatureCollection对象下:
* -- List<feature>
* -- --Feature :id,type,Properties,Geometry
* -- -- --Geometry : type ,coordinates
* -- -- --Properties : 自定义属性,
* */json
* 数据结构:
* {
* "type": "FeatureCollection",
* "features": [
* {
* "geometry": {
* "coordinates": [
* [
* [
* [114.2563, 22.1603],
* [114.2544, 22.1639],
* [114.251, 22.1662],
* [114.2478, 22.1702],
* [114.2501, 22.1738],
* [114.2639, 22.1834],
* [114.2686, 22.1834],
* [114.2714, 22.1725],
* [114.275, 22.166],
* [114.2754, 22.1639],
* [114.2669, 22.1612],
* [114.2563, 22.1603]
* ]
* ]
* ],
* "type": "MultiPolygon"
* },
* "id": "map.923",
* "type": "Feature",
* "properties": {
* "ADCODE99": 810000,
* "AREA": 0.0,
* "BOU2_4M_": 925,
* "ADCODE93": 810000,
* "BOU2_4M_ID": 3114,
* "PERIMETER": 0.079,
* "NAME": "香港特别行政区"
* }
* },
* {
* "geometry": {
* "coordinates": [
* [
* [
* [114.2989, 22.1781],
* [114.3006, 22.1789],
* [114.3021, 22.179],
* [114.3024, 22.178],
* [114.302, 22.1763],
* [114.3009, 22.1755],
* [114.2995, 22.1762],
* [114.299, 22.1774],
* [114.2989, 22.1781]
* ]
* ]
* ],
* "type": "MultiPolygon"
* },
* "id": "map.924",
* "type": "Feature",
* "properties": {
* "ADCODE99": 810000,
* "AREA": 0.0,
* "BOU2_4M_": 926,
* "ADCODE93": 810000,
* "BOU2_4M_ID": 3115,
* "PERIMETER": 0.011,
* "NAME": "香港特别行政区"
* }
* }]
* }v##一、项目
###1.pom依赖
xml
<!--geotools,最新版不行21.2-->
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-geojson</artifactId>
<version>${geotools.version}</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-shapefile</artifactId>
<version>${geotools.version}</version>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.28</version>
</dependency>###2.详细代码
####1.shp转geojson
java
public static String shpToGeojson(String infilePath,String outfilePath){
return readshp(infilePath,outfilePath);
}
public static String shpToGeojson(String infilePath){
return readshp(infilePath,null);
}
/**
* 读取shp文件转为json字符串
* @param infilePath
* @param outfilePath
* @return
*/
private static String readshp(String infilePath,String outfilePath){
//最外面一层
JSONObject geojson=new JSONObject();
geojson.put("type","FeatureCollection");
JSONArray array = new JSONArray();
//featureJson专门转json,精确到小数15位,一定要注意
FeatureJSON fjson = new FeatureJSON(new GeometryJSON(15));
//1.得到SimpleFeatureCollection
SimpleFeatureCollection featureCollection = getFeatureCollection(infilePath);
//2.得到所有的features
SimpleFeatureIterator features = featureCollection.features();
//3.遍历每个features
while (features.hasNext()){
SimpleFeature feature = features.next();
StringWriter writer = new StringWriter();
try {
//4.feature对象转json字符串
fjson.writeFeature(feature, writer);
String feartureStr=writer.toString();
//5.json字符串转json对象
JSONObject geojsonObject = JSON.parseObject(feartureStr);
//6.套入fearture数组
array.add(geojsonObject);
} catch (IOException e) {
e.printStackTrace();
}
}
geojson.put("features",array);
features.close();
//7.最终的json转字符串
String geojsonStr = geojson.toJSONString();
//8.可选 输出到文件
if(StringUtils.isNotBlank(outfilePath)){
writeFile(outfilePath,geojsonStr);
}
return geojsonStr;
}
/**
* 读取shp文件第一步
* @param path
* @return
*/
private static SimpleFeatureSource readStoreByShp(String path) {
//1.传入文件路径
File file = new File(path);
//2.根据文件的url获得FileDataStore对象
FileDataStore store = null;
try {
//*******************可以获取url****************
// store = FileDataStoreFinder.getDataStore(file);
// URL url = new URL("https://gitee.com/liuchenyun/JavaSe/tree/master/map/map.shp");
// URLConnection urlconn = url.openConnection(); // 试图连接并取得返回状态码
// urlconn.connect();
store = FileDataStoreFinder.getDataStore(file);
//转码
((ShapefileDataStore) store).setCharset(Charset.forName("GBK"));
//3.得到SimpleFeatureSource
return store.getFeatureSource();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 读取shp第一步第二种方式
* @param path
* @return
*/
private static SimpleFeatureSource readStoreByShp2(String path){
//1.传入文件路径
File file = new File(path);
//2.根据文件的url得到ShapefileDataStore,这是FileDataStore子类实现
ShapefileDataStore shpDataStore = null;
try {
shpDataStore = new ShapefileDataStore(file.toURL());
shpDataStore.setCharset(Charset.forName("UTF-8"));
String typeName = shpDataStore.getTypeNames()[0];
//3.得到SimpleFeatureSource
return shpDataStore.getFeatureSource(typeName);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 读取shp第二部
* @param path
* @return
*/
private static SimpleFeatureCollection getFeatureCollection(String path){
try {
//1.得到SimpleFeatureSource
SimpleFeatureSource source = readStoreByShp(path);
if(source==null){
return null;
}
//2.返回SimpleFeatureCollection对象
return source.getFeatures();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}2.geojson转shp
java
/**
* geojson转shp,shx,dbf
* @param geojson
* @param shpPath
* @throws IOException
*/
public static void geojsonToShp(String geojson, String shpPath) {
GeometryJSON gjson = new GeometryJSON();
//1.创建shp输出文件
File file = new File(shpPath);
//2.得到ShapefileDataStore对象 一个空的store
Map<String, Serializable> params = new HashMap<>();
try {
params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL());
ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);
//3.定义图形信息和属性信息。。。
SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
// tb.setCRS(DefaultGeographicCRS.WGS84);
tb.setName("shapefile");
//feature的type
Class<?> geoType = getFutrueType(geojson);
tb.add("the_geom", geoType);
//动态获取properties属性
JSONObject json = JSON.parseObject(geojson);
JSONArray features = (JSONArray) json.get("features");
JSONObject featureStr1 = (JSONObject) features.get(0);
JSONObject properties1 = (JSONObject)featureStr1.get("properties");
Set<String> strings1 = properties1.keySet();
for (String key : strings1) {
//这有问题,固定死了string,如何获取value的类型?
Object o = properties1.get(key);
tb.add(key, String.class);
}
ds.createSchema(tb.buildFeatureType());
ds.setCharset(Charset.forName("UTF-8"));
//4.从空仓库里得到FeatureWriter对像
FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(ds.getTypeNames()[0], Transaction.AUTO_COMMIT);
for(int i=0,len=features.size();i<len;i++){
JSONObject featureStr = (JSONObject) features.get(i);
JSONObject properties = (JSONObject)featureStr.get("properties");
Set<String> strings = properties.keySet();
//空的feature
SimpleFeature feature = writer.next();
//得到每个feature,并读取
String strFeature = features.get(i).toString();
Reader reader = new StringReader(strFeature);
//设置属性,从geojson中取出properties对象的值
feature.setAttribute("the_geom",gjson.readMultiPolygon(reader));
for (String key : strings) {
feature.setAttribute(key,properties.get(key).toString());
}
//往仓库里输出feature
writer.write();
}
writer.close();
ds.dispose();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 根据geojson字符串中的feature中的type
* @param geojson
* @return
*/
public static Class<?> getFutrueType(String geojson){
//每个feature的type都是一样的
JSONObject json = JSON.parseObject(geojson);
JSONArray features = (JSONArray) json.get("features");
JSONObject feature0 = JSON.parseObject(features.get(0).toString());
String strType = ((JSONObject)feature0.get("geometry")).getString("type").toString();
Class<?> geoType = null;
switch(strType){
case "Point":
geoType = Point.class;
case "MultiPoint":
geoType = MultiPoint.class;
case "LineString":
geoType = LineString.class;
case "MultiLineString":
geoType = MultiLineString.class;
case "Polygon":
geoType = Polygon.class;
case "MultiPolygon":
geoType = MultiPolygon.class;
}
return geoType;
}3.输出文件
/**
* 输出到文件
* @param filePath
* @param geojsonStr
*/
private static void writeFile(String filePath,String geojsonStr){
OutputStreamWriter outputStreamWriter = null;
try {
File outputfile=new File(filePath);
FileOutputStream fileOutputStream=new FileOutputStream(outputfile);
outputStreamWriter=new OutputStreamWriter(fileOutputStream,"utf-8");
outputStreamWriter.write(geojsonStr);
outputStreamWriter.flush();
outputStreamWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}二、总结
1.问题
1.shp转geojson
type:是固定的2.geojson转shp
dbf文件变大三、精确代码
java
package cn.lcy.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.vividsolutions.jts.geom.*;
import org.apache.commons.lang3.StringUtils;
import org.geotools.data.FeatureWriter;
import org.geotools.data.FileDataStore;
import org.geotools.data.FileDataStoreFinder;
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 java.io.*;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
/**
* @author 刘琛运
* @date 2019/8/15 14:17
*
*/
public class GeoTools2 {
public static String shpToGeojson(String infilePath,String outfilePath){
return readshp(infilePath,outfilePath);
}
public static String shpToGeojson(String infilePath){
return readshp(infilePath,null);
}
/**
* 读取shp文件转为json字符串
* @param infilePath
* @param outfilePath
* @return
*/
private static String readshp(String infilePath,String outfilePath){
//最外面一层
JSONObject geojson=new JSONObject();
geojson.put("type","FeatureCollection");
JSONArray array = new JSONArray();
//featureJson专门转json,精确到小数15位,一定要注意
FeatureJSON fjson = new FeatureJSON(new GeometryJSON(15));
//1.得到SimpleFeatureCollection
SimpleFeatureCollection featureCollection = getFeatureCollection(infilePath);
//2.得到所有的features
SimpleFeatureIterator features = featureCollection.features();
//3.遍历每个features
while (features.hasNext()){
SimpleFeature feature = features.next();
StringWriter writer = new StringWriter();
try {
//4.feature对象转json字符串
fjson.writeFeature(feature, writer);
String feartureStr=writer.toString();
//5.json字符串转json对象
JSONObject geojsonObject = JSON.parseObject(feartureStr);
//6.套入fearture数组
array.add(geojsonObject);
} catch (IOException e) {
e.printStackTrace();
}
}
geojson.put("features",array);
features.close();
//7.最终的json转字符串
String geojsonStr = geojson.toJSONString();
//8.可选 输出到文件
if(StringUtils.isNotBlank(outfilePath)){
writeFile(outfilePath,geojsonStr);
}
return geojsonStr;
}
/**
* 读取shp文件第一步
* @param path
* @return
*/
private static SimpleFeatureSource readStoreByShp(String path) {
//1.传入文件路径
File file = new File(path);
//2.根据文件的url获得FileDataStore对象
FileDataStore store = null;
try {
//*******************可以获取url****************
// store = FileDataStoreFinder.getDataStore(file);
// URL url = new URL("https://gitee.com/liuchenyun/JavaSe/tree/master/map/map.shp");
// URLConnection urlconn = url.openConnection(); // 试图连接并取得返回状态码
// urlconn.connect();
store = FileDataStoreFinder.getDataStore(file);
//转码
((ShapefileDataStore) store).setCharset(Charset.forName("GBK"));
//3.得到SimpleFeatureSource
return store.getFeatureSource();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 读取shp第一步第二种方式
* @param path
* @return
*/
private static SimpleFeatureSource readStoreByShp2(String path){
//1.传入文件路径
File file = new File(path);
//2.根据文件的url得到ShapefileDataStore,这是FileDataStore子类实现
ShapefileDataStore shpDataStore = null;
try {
shpDataStore = new ShapefileDataStore(file.toURL());
shpDataStore.setCharset(Charset.forName("UTF-8"));
String typeName = shpDataStore.getTypeNames()[0];
//3.得到SimpleFeatureSource
return shpDataStore.getFeatureSource(typeName);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 读取shp第二部
* @param path
* @return
*/
private static SimpleFeatureCollection getFeatureCollection(String path){
try {
//1.得到SimpleFeatureSource
SimpleFeatureSource source = readStoreByShp(path);
if(source==null){
return null;
}
//2.返回SimpleFeatureCollection对象
return source.getFeatures();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* geojson转shp,shx,dbf
* @param geojson
* @param shpPath
* @throws IOException
*/
public static void geojsonToShp(String geojson, String shpPath) {
GeometryJSON gjson = new GeometryJSON();
//1.创建shp输出文件
File file = new File(shpPath);
//2.得到ShapefileDataStore对象 一个空的store
Map<String, Serializable> params = new HashMap<>();
try {
params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL());
ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);
//3.定义图形信息和属性信息。。。
SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
tb.setCRS(DefaultGeographicCRS.WGS84);
tb.setName("shapefile");
//feature的type
Class<?> geoType = getFutrueType(geojson);
tb.add("the_geom", geoType);
//动态获取properties属性
JSONObject json = JSON.parseObject(geojson);
JSONArray features = (JSONArray) json.get("features");
JSONObject featureStr1 = (JSONObject) features.get(0);
JSONObject properties1 = (JSONObject)featureStr1.get("properties");
Set<String> strings1 = properties1.keySet();
for (String key : strings1) {
//需要先给属性设置类型
Object value = properties1.get(key);
Class<?> type = getType(value);
tb.add(key, type);
}
ds.createSchema(tb.buildFeatureType());
ds.setCharset(Charset.forName("GBK"));
//4.从空仓库里得到FeatureWriter对像
FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(ds.getTypeNames()[0], Transaction.AUTO_COMMIT);
for(int i=0,len=features.size();i<len;i++){
JSONObject featureStr = (JSONObject) features.get(i);
JSONObject properties = (JSONObject)featureStr.get("properties");
Set<String> strings = properties.keySet();
//空的feature
SimpleFeature feature = writer.next();
//得到每个feature,并读取
String strFeature = features.get(i).toString();
Reader reader = new StringReader(strFeature);
//设置属性,从geojson中取出properties对象的值
feature.setAttribute("the_geom",gjson.readMultiPolygon(reader));
for (String key : strings) {
feature.setAttribute(key,properties.get(key).toString());
}
//往仓库里输出feature
writer.write();
}
writer.close();
ds.dispose();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 根据geojson字符串中的feature中的type
* @param geojson
* @return
*/
private static Class<?> getFutrueType(String geojson){
//每个feature的type都是一样的
JSONObject json = JSON.parseObject(geojson);
JSONArray features = (JSONArray) json.get("features");
JSONObject feature0 = JSON.parseObject(features.get(0).toString());
String strType = ((JSONObject)feature0.get("geometry")).getString("type").toString();
Class<?> geoType = null;
switch(strType){
case "Point":
geoType = Point.class;
case "MultiPoint":
geoType = MultiPoint.class;
case "LineString":
geoType = LineString.class;
case "MultiLineString":
geoType = MultiLineString.class;
case "Polygon":
geoType = Polygon.class;
case "MultiPolygon":
geoType = MultiPolygon.class;
}
return geoType;
}
/**
* 判断类型
* @param param
* @return
*/
private static Class<?> getType(Object param){
Class<?> geoType = null;
if (param instanceof String) {
//可能是个字符串的数值
String params = (String)param;
if(Pattern.compile("^[-\\+]?[\\d]*$").matcher(params).matches()){
return Integer.class;
}
//可能是个字符串的数值
if(Pattern.compile("^[+-]?[0-9.]+$").matcher(params).find()){
return Double.class;
}
return String.class;
}else if (param instanceof Integer) {
return Integer.class;
} else if (param instanceof Double) {
return Double.class;
}else if(param instanceof BigDecimal){
return Integer.class;
}
else {
return String.class;
}
}
/**
* 输出到文件
* @param filePath
* @param geojsonStr
*/
private static void writeFile(String filePath,String geojsonStr){
OutputStreamWriter outputStreamWriter = null;
try {
File outputfile=new File(filePath);
FileOutputStream fileOutputStream=new FileOutputStream(outputfile);
outputStreamWriter=new OutputStreamWriter(fileOutputStream,"utf-8");
outputStreamWriter.write(geojsonStr);
outputStreamWriter.flush();
outputStreamWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
String in = "D:\\map\\map.shp";
String out = "D:\\map\\map.json";
// String in = "D:\\map\\map\\map.shp";
// String out = "D:\\map\\map\\map.json";
// String in = "D:\\vector\\北京.shp";
// String out = "D:\\vector\\北京.json";
String geojson = shpToGeojson(in,out);
String s = "D:\\map\\map\\map.shp";
geojsonToShp(geojson,s);
// System.out.println(geojson);
}
/*
* 数据结构:
* FeatureCollection对象下:
* -- List<feature>
* -- --Feature :id,type,Properties,Geometry
* -- -- --Geometry : type ,coordinates
* -- -- --Properties : 自定义属性,
* */
}