场景
有一个文件夹,里面有若干个shp文件和子文件夹,子文件夹中包含还包含shp或者子文件夹…
需要一个util把全部的shp都提取出来,提取空间信息(或者外加属性信息,或者可以提取指定的属性信息)。
实现思路
1. 空间信息的工具用geotools API
2. 循环读取shp文件夹下的shp文件的绝对路径出来
3. 增加个过滤的条件,用于提取只希望提取的属性值出来
实现
依赖
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-shapefile</artifactId>
<version>26.4</version>
</dependency>
<dependency>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
<version>28.2-jre</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-cql</artifactId>
<version>26.4</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-main</artifactId>
<version>26.4</version>
</dependency>
代码
import org.apache.commons.lang3.StringUtils;
import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFinder;
import org.geotools.data.FeatureSource;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.store.ContentFeatureCollection;
import org.geotools.data.store.ContentFeatureSource;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.Geometry;
import org.opengis.feature.GeometryAttribute;
import org.opengis.feature.Property;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.Filter;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
public class ShapeFileUtil {
/**
* convert shpFileType to db field type
* 备注:目前arcgis的字段类型有:短整型 长整型 浮点型 双精度 文本 日期
*
* @param value
* @return
*/
public static String convertShpFieldType2H2GISOrPG(Class value) throws Exception {
if (value == String.class) {//文本
return "varchar";
}
if (value == Integer.class) {//短整型
return "int";
}
if (value == Long.class) {//长整型
return "bigint";
}
if (value == Double.class || value == Float.class) {//浮点型 双精度 保留精度,比如在金币上运算更安全
return "numeric";
}
if (value == Date.class) {
return "TIMESTAMP WITH TIME ZONE ";//日期, 使用包含时区的来处理
}
if (Geometry.class.isAssignableFrom(value)) {
return "geometry";
}
//除了上述,真不知道还会有啥了。除非arcgis的shp又增加了新类型?!那无能为力了,抛出异常吧
throw new Exception("不支持的类型!" + value.getName());
//
// if (value.getSuperclass().getName().equals(String.class))
// return null;
}
/**
* 读取shp的bbox并返回
* @param filePaths
* @return GeomAttrWrapper.bboxMap属性中存储每个shp对应的bbox
* @throws IOException
*/
public static GeomAttrWrapper readBboxFromFile(List<String> filePaths) throws IOException {
Map<String, Envelope> bboxMap = new HashMap<>();
for (String filePath : filePaths) {
if (!filePath.endsWith(".shp")) {
continue;
}
File file = new File(filePath);
Map<String, Object> map = new HashMap<>();
map.put("url", file.toURI().toURL());
ShapefileDataStore dataStore = new ShapefileDataStore(file.toURI().toURL());//DataStoreFinder.getDataStore(map);
dataStore.setCharset(Charset.forName("GBK"));
String typeName = dataStore.getTypeNames()[0];
FeatureSource<SimpleFeatureType, SimpleFeature> source =
dataStore.getFeatureSource(typeName);
Filter filter = Filter.INCLUDE; // ECQL.toFilter("BBOX(THE_GEOM, 10,20,30,40)")
FeatureCollection<SimpleFeatureType, SimpleFeature> collection = source.getFeatures(filter);
bboxMap.put(filePath, collection.getBounds());
// final CoordinateReferenceSystem coordinateReferenceSystem = collection.getBounds().getCoordinateReferenceSystem();
// final String crsCode = CRS.toSRS(coordinateReferenceSystem, true);
dataStore.dispose();
}
return new GeomAttrWrapper(null, null, bboxMap);
}
/**
* 从shp文件中读取geometry和属性字段数据
*
* @param filePaths shp文件在磁盘下的绝对路径
* @param returnAllAttrs 若为true,则返回全部的属性;若为false,则提取filterAttrs中指定的属性和geometry;filterAttrs为null或者空,则只提取geometry
* @param filterAttrs 用于过滤出希望返回的属性
* @return GeomAttrWrapper
* @throws Exception
*/
public static GeomAttrWrapper readShapeAndFieldsFromFile(List<String> filePaths, boolean returnAllAttrs, Set<String> filterAttrs) throws Exception {
Map<String, List<ShpGeomWithAttr>> geoMap = new HashMap<>();
Map<String, Envelope> bboxMap = new HashMap<>();
boolean getExpectedAttrs = filterAttrs != null && filterAttrs.size() > 0 ? true : false;
Map<String, Class> attrTypes = new HashMap<>();
for (String filePath : filePaths) {
if (!filePath.endsWith(".shp")) {
continue;
}
List<ShpGeomWithAttr> geometries = new ArrayList<>();
File file = new File(filePath);
Map<String, Object> map = new HashMap<>();
map.put("url", file.toURI().toURL());
ShapefileDataStore dataStore = new ShapefileDataStore(file.toURI().toURL());//DataStoreFinder.getDataStore(map);
dataStore.setCharset(Charset.forName("GBK"));
String typeName = dataStore.getTypeNames()[0];
FeatureSource<SimpleFeatureType, SimpleFeature> source =
dataStore.getFeatureSource(typeName);
Filter filter = Filter.INCLUDE; // ECQL.toFilter("BBOX(THE_GEOM, 10,20,30,40)")
FeatureCollection<SimpleFeatureType, SimpleFeature> collection = source.getFeatures(filter);
bboxMap.put(filePath, collection.getBounds());
final CoordinateReferenceSystem coordinateReferenceSystem = collection.getBounds().getCoordinateReferenceSystem();
final String crsCode = CRS.toSRS(coordinateReferenceSystem, true);
int srid = 0;
try {
srid = Integer.parseInt(crsCode);
} catch (NumberFormatException e) {//有时候,prj文件中没有出现’AUTHORITY["EPSG",4326]‘,就会解不了srid的int出来,就会报错,此时就不管它了,没办法
// e.printStackTrace();
}
try (FeatureIterator<SimpleFeature> features = collection.features()) {
while (features.hasNext()) {
SimpleFeature feature = features.next();
final GeometryAttribute geometryProperty = feature.getDefaultGeometryProperty();
Object value = geometryProperty.getValue();
if (value instanceof Geometry) {
Geometry geometry = (Geometry) value;
geometry.setSRID(srid);
Map<String, Object> properties = null;
if (returnAllAttrs) {// 全都返回,则直接全都返回
final Collection<Property> prps = feature.getProperties();
properties = new HashMap<>(prps.size());
for (Property prp : prps) {
final String name = prp.getName().getLocalPart().toLowerCase(Locale.ROOT);
properties.put(name, prp.getValue());
final Class type = attrTypes.get(name);
if (type == null) {
attrTypes.put(name, prp.getType().getBinding());
}
}
} else if (getExpectedAttrs) {
properties = new HashMap<>(filterAttrs.size());
final Collection<Property> prps = feature.getProperties();
for (Property prp : prps) {
final String name = prp.getName().getLocalPart().toLowerCase(Locale.ROOT);
if (filterAttrs.contains(name)) {
properties.put(name, prp.getValue());
final Class type = attrTypes.get(name);
if (type == null) {
attrTypes.put(name, prp.getType().getBinding());
}
}
}
}
ShpGeomWithAttr shpGeomWithAttr = new ShpGeomWithAttr(geometry, properties);
geometries.add(shpGeomWithAttr);
}
}
} catch (Exception e) {
//do nothing...
}
dataStore.dispose();
geoMap.put(filePath, geometries);
}
return new GeomAttrWrapper(geoMap, attrTypes, bboxMap);
}
/**
* 从shp文件中读取geometry数据
*
* @param filePaths shp文件在磁盘下的绝对路径
* @return
* @throws Exception
*/
public static Map<String, List<Geometry>> readShapeFromFile(List<String> filePaths) throws Exception {
Map<String, List<Geometry>> geoMap = new HashMap<>();
for (String filePath : filePaths) {
if (!filePath.endsWith(".shp")) {
continue;
}
List<Geometry> geometries = new ArrayList<>();
File file = new File(filePath);
Map<String, Object> map = new HashMap<>();
map.put("url", file.toURI().toURL());
DataStore dataStore = DataStoreFinder.getDataStore(map);
String typeName = dataStore.getTypeNames()[0];
FeatureSource<SimpleFeatureType, SimpleFeature> source =
dataStore.getFeatureSource(typeName);
Filter filter = Filter.INCLUDE; // ECQL.toFilter("BBOX(THE_GEOM, 10,20,30,40)")
FeatureCollection<SimpleFeatureType, SimpleFeature> collection = source.getFeatures(filter);
final CoordinateReferenceSystem coordinateReferenceSystem = collection.getBounds().getCoordinateReferenceSystem();
final String crsCode = CRS.toSRS(coordinateReferenceSystem, true);
int srid = 0;
try {
srid = Integer.parseInt(crsCode);
} catch (NumberFormatException e) {//有时候,prj文件中没有出现’AUTHORITY["EPSG",4326]‘,就会解不了srid的int出来,就会报错,此时就不管它了,没办法
// e.printStackTrace();
}
try (FeatureIterator<SimpleFeature> features = collection.features()) {
while (features.hasNext()) {
SimpleFeature feature = features.next();
// final Collection<Property> properties = feature.getProperties();
// final Property name = feature.getProperty("Name");
// final List<Object> attributes = feature.getAttributes();
// final Object name1 = feature.getAttribute("Name");//value本身
// Property name.getType().getBinding().getName();//可以获取类型
//name.getName();//获取字段名称
//name.getValue();//获取值
final GeometryAttribute geometryProperty = feature.getDefaultGeometryProperty();
Object value = geometryProperty.getValue();
if (value instanceof Geometry) {
Geometry geometry = (Geometry) value;
geometry.setSRID(srid);
geometries.add(geometry);
// Envelope geomEnvelope = geometry.getEnvelopeInternal();
// envelope.expandToInclude(geomEnvelope);
}
}
}
dataStore.dispose();
geoMap.put(filePath, geometries);
}
return geoMap;
}
/**
*
* @param baseDir shp文件(夹)的绝对路径
* @return 返回该文件(夹)的所有的shp的绝对路径
*/
public static List<String> getShpFilePaths(String baseDir) {
if (baseDir.endsWith(".shp")) {
return new ArrayList<String>() {{
add(baseDir);
}};
}
File fileDir = new File(baseDir);
if (!fileDir.exists()) {
return null;
}
List<String> shpList = new ArrayList<>();
List<String> dirs = new ArrayList<>() {{
add(baseDir);
}};
while (true) {
List<String> newDirs = null;
if (dirs != null && dirs.size() > 0) {
for (String dir : dirs) {
File file = new File(dir);
final File[] files = file.listFiles();
if (files != null && files.length > 0) {
for (File aFile : files) {
if (aFile.getName().endsWith(".shp")) {
shpList.add(aFile.getAbsolutePath());
} else if (aFile.isDirectory()) {
newDirs = newDirs == null ? new ArrayList<>() : newDirs;
newDirs.add(aFile.getAbsolutePath());
}
}
}
}
dirs = newDirs;
} else {
break;
}
}
return shpList;
}
public static class ShpGeomWithAttr {
private Geometry geometry;
private Map<String, Object> properties;
public ShpGeomWithAttr(Geometry geometry, Map<String, Object> properties) {
this.geometry = geometry;
this.properties = properties;
}
public Geometry getGeometry() {
return geometry;
}
public void setGeometry(Geometry geometry) {
this.geometry = geometry;
}
public Map<String, Object> getProperties() {
return properties;
}
public void setProperties(Map<String, Object> properties) {
this.properties = properties;
}
}
public static class GeomAttrWrapper {
private Map<String, List<ShpGeomWithAttr>> geoMap;
private Map<String, Class> attrTypeMap;
private Map<String, Envelope> bboxMap;
public GeomAttrWrapper(Map<String, List<ShpGeomWithAttr>> geoMap, Map<String, Class> attrTypeMap, Map<String, Envelope> bboxMap) {
this.geoMap = geoMap;
this.attrTypeMap = attrTypeMap;
this.bboxMap = bboxMap;
}
public Map<String, List<ShpGeomWithAttr>> getGeoMap() {
return geoMap;
}
public void setGeoMap(Map<String, List<ShpGeomWithAttr>> geoMap) {
this.geoMap = geoMap;
}
public Map<String, Class> getAttrTypeMap() {
return attrTypeMap;
}
public void setAttrTypeMap(Map<String, Class> attrTypeMap) {
this.attrTypeMap = attrTypeMap;
}
public Map<String, Envelope> getBboxMap() {
return bboxMap;
}
public void setBboxMap(Map<String, Envelope> bboxMap) {
this.bboxMap = bboxMap;
}
}
}
版权声明:本文为jfqqqqq原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。