解析shape文件转换为geojson,支持坐标系转换工具
package com.sboot.test;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import org.geotools.data.FeatureSource;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.geojson.GeoJSON;
import org.geotools.geojson.GeoJSONUtil;
import org.geotools.geojson.geom.GeometryJSON;
import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.json.simple.JSONStreamAware;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.geometry.BoundingBox;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import java.io.*;
import java.nio.charset.Charset;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static org.geotools.geojson.GeoJSONUtil.*;
public class GeoShapeFileUtil {
public static void readShapeFile(File shpFile) {
try {
FeatureSource featuresource = getFeatureSource(shpFile);
//读取要素
SimpleFeatureCollection simpleFeatureCollection = (SimpleFeatureCollection) featuresource.getFeatures();
//获取当前矢量数据有哪些属性字段值
List<AttributeDescriptor> attributes = simpleFeatureCollection.getSchema().getAttributeDescriptors();
SimpleFeatureIterator simpleFeatureIterator = simpleFeatureCollection.features();
//
while (simpleFeatureIterator.hasNext()) {
SimpleFeature simpleFeature = simpleFeatureIterator.next();
attributes.stream().forEach((a) -> {
//读取属性值,业务处理,存储
System.out.println(simpleFeature.getAttribute(a.getLocalName()));
});
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//关闭资源
simpleFeatureIterator.close();
}
}
private static FeatureSource getFeatureSource(File shpFile) throws Exception {
ShapefileDataStore shapefileDataStore = new ShapefileDataStore(shpFile.toURI().toURL());
String charset = getShapeFileCharsetName(shpFile.getAbsolutePath().replace(".shp", ".cpg"));
System.out.println("文件:" + shpFile.getName() + ",编码格式:" + charset);
shapefileDataStore.setCharset(Charset.forName(charset));
return shapefileDataStore.getFeatureSource(shapefileDataStore.getTypeNames()[0]);
}
/**
* shapeFile转Geojson文件
*
* @param shpFile
* @param outFile
*/
public static void shapeFileToGeoJson(File shpFile, File outFile) {
try {
FeatureSource featuresource = getFeatureSource(shpFile);
//读取要素
SimpleFeatureCollection simpleFeatureCollection = (SimpleFeatureCollection) featuresource.getFeatures();
System.out.println(simpleFeatureCollection.getSchema().getCoordinateReferenceSystem());
GeoJSON.write(simpleFeatureCollection, outFile);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* shapeFile转Geojson文件
*
* @param shpFile shape文件
* @param outFile 输出geojson文件
* @param outSrsCode 输出坐标系
*/
public static void shapeFileToGeoJson(File shpFile, File outFile, String outSrsCode) {
try {
FeatureSource featuresource = getFeatureSource(shpFile);
//读取shpa坐标系
CoordinateReferenceSystem shapeCRS = featuresource.getSchema().getCoordinateReferenceSystem();
//输出目标坐标系
CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:" + outSrsCode, true);
//投影转换系统
MathTransform transform = CRS.findMathTransform(shapeCRS, targetCRS, true);
//读取要素
SimpleFeatureCollection simpleFeatureCollection = (SimpleFeatureCollection) featuresource.getFeatures();
//FeatureJSON
writeFeatureCollection(simpleFeatureCollection, outFile, targetCRS, transform);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void writeFeatureCollection(SimpleFeatureCollection collection, File outFile, CoordinateReferenceSystem crs, MathTransform transform) throws IOException {
LinkedHashMap obj = new LinkedHashMap();
obj.put("type", "FeatureCollection");
if (collection.getSchema().getGeometryDescriptor() != null) {
final ReferencedEnvelope bounds = collection.getBounds();
// if (bounds != null) {
// obj.put("bbox", new JSONStreamAware() {
// public void writeJSONString(Writer out) throws IOException {
// JSONArray.writeJSONString(Arrays.asList(bounds.getMinX(),
// bounds.getMinY(), bounds.getMaxX(), bounds.getMaxY()), out);
// }
// });
// }
if (crs != null) {
obj.put("crs", createCRS(crs));
}
}
obj.put("features", new FeatureCollectionEncoder(collection, new GeometryJSON(8), transform));
GeoJSONUtil.encode(obj, outFile);
}
private static Map<String, Object> createCRS(CoordinateReferenceSystem crs) throws IOException {
Map<String, Object> obj = new LinkedHashMap<String, Object>();
obj.put("type", "name");
Map<String, Object> props = new LinkedHashMap<String, Object>();
if (crs == null) {
props.put("name", "EPSG:4326");
} else {
try {
String identifier = CRS.lookupIdentifier(crs, true);
props.put("name", identifier);
} catch (FactoryException e) {
throw (IOException) new IOException("Error looking up crs identifier").initCause(e);
}
}
obj.put("properties", props);
return obj;
}
static class FeatureCollectionEncoder implements JSONStreamAware {
FeatureCollection features;
GeometryJSON gjson;
MathTransform transform;
public FeatureCollectionEncoder(FeatureCollection features, GeometryJSON gjson, MathTransform transform) {
this.features = features;
this.gjson = gjson;
this.transform = transform;
}
public void writeJSONString(Writer out) throws IOException {
out.write("[");
FeatureIterator i = features.features();
try {
if (i.hasNext()) {
SimpleFeature f = (SimpleFeature) i.next();
out.write(toJSONString(f));
while (i.hasNext()) {
out.write(",");
f = (SimpleFeature) i.next();
out.write(toJSONString(f));
}
}
} catch (TransformException e) {
throw new RuntimeException(e);
} finally {
if (i != null) {
i.close();
}
}
out.write("]");
out.flush();
}
public String toJSONString(SimpleFeature feature) throws TransformException {
SimpleFeatureType featureType = feature.getType();
StringBuilder sb = new StringBuilder();
sb.append("{");
//type
entry("type", "Feature", sb);
sb.append(",");
//geometry
if (feature.getDefaultGeometry() != null) {
Object geometry = feature.getDefaultGeometry();
if (transform != null) {
geometry = JTS.transform((Geometry) feature.getDefaultGeometry(), transform);
}
string("geometry", sb).append(":")
.append(gjson.toString((Geometry) geometry));
sb.append(",");
}
//properties
int gindex = featureType.getGeometryDescriptor() != null ?
featureType.indexOf(featureType.getGeometryDescriptor().getLocalName()) :
-1;
string("properties", sb).append(":").append("{");
boolean attributesWritten = false;
for (int i = 0; i < featureType.getAttributeCount(); i++) {
AttributeDescriptor ad = featureType.getDescriptor(i);
// skip the default geometry, it's already encoded
if (i == gindex) {
continue;
}
Object value = feature.getAttribute(i);
if (value == null) {
//skip
continue;
}
attributesWritten = true;
// handle special types separately, everything else as a string or literal
if (value instanceof Envelope) {
array(ad.getLocalName(), gjson.toString((Envelope) value), sb);
} else if (value instanceof BoundingBox) {
array(ad.getLocalName(), gjson.toString((BoundingBox) value), sb);
} else if (value instanceof Geometry) {
string(ad.getLocalName(), sb).append(":")
.append(gjson.toString((Geometry) value));
} else {
entry(ad.getLocalName(), value, sb);
}
sb.append(",");
}
if (attributesWritten) {
sb.setLength(sb.length() - 1);
}
sb.append("},");
//id
entry("id", feature.getID(), sb);
sb.append("}");
return sb.toString();
}
}
/**
* @param path cpg文件路径
* @return
* @throws Exception
*/
private static String getShapeFileCharsetName(String path) throws Exception {
File pFile = new File(path);
if (pFile.exists() && !pFile.isFile()) {
return "GBK";
}
File file = new File(path);
String encode = "GBK";
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
String tempString = null;
// 一次读入一行,直到读入null为文件结束
while ((tempString = reader.readLine()) != null) {
// 显示行号
if ("UTF-8".equals(tempString.toUpperCase())) {
encode = "UTF-8";
break;
}
break;
}
reader.close();
} catch (IOException e) {
// e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e1) {
}
}
}
return encode;
}
}
测试用例代码
package com.sboot.test;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
public class GeoShapeFileTest {
@Test
public void shapeFileToGeoJsonTest() throws IOException {
String dir = "C:\\Users\\admin\\Desktop\\split\\split";
String outDir = "C:\\Users\\admin\\Desktop\\split";
File dirFile = new File(dir);
File[] files = dirFile.listFiles(f -> f.getName().endsWith(".shp"));
for (File shapeFile : files) {
String shapeName = shapeFile.getName();
System.out.println(shapeName);
File geoJsonFile = new File(outDir, shapeName + ".json");
geoJsonFile.createNewFile();
GeoShapeFileUtil.shapeFileToGeoJson(shapeFile, geoJsonFile, "4490");
}
}
@Test
public void readShapefileTest() {
String shapeFileName = "C:\\Users\\admin\\Desktop\\test.shp";
GeoShapeFileUtil.readShapeFile(new File(shapeFileName));
}
}
引入geotools相关jar包
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-shapefile</artifactId>
<version>17.1</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-api</artifactId>
<version>17.1</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-data</artifactId>
<version>17.1</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-geojson</artifactId>
<version>17.1</version>
</dependency>
<!-- 坐标系转换 -->
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-epsg-hsql</artifactId>
<version>17.1</version>
</dependency>