geotools读取文件夹下的shp数据包括属性

  • Post author:
  • Post category:其他


场景

有一个文件夹,里面有若干个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 版权协议,转载请附上原文出处链接和本声明。