Java 读取任意shapefile的所有字段,并插入到MongoDB数据库(Spring Boot)

54 篇文章 2 订阅
33 篇文章 1 订阅


Java 读取任意shapefile的所有字段,并插入到MongoDB数据库(Spring Boot)

  • 亮点:动态获取字段信息,动态创建数据库表信息,支持任意shapefile数据
  • pom
<repositories>
        <repository>
            <id>maven2-repository.dev.java.net</id>
            <name>Java.net repository</name>
            <url>http://download.java.net/maven/2</url>
        </repository>
        <repository>
            <id>osgeo</id>
            <name>Open Source Geospatial Foundation Repository</name>
            <url>http://download.osgeo.org/webdav/geotools/</url>
        </repository>
        <repository>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
            <id>boundless</id>
            <name>Boundless Maven Repository</name>
            <url>http://repo.boundlessgeo.com/main</url>
        </repository>
</repositories>
<dependency>
  <groupId>org.geotools</groupId>
    <artifactId>gt-shapefile</artifactId>
    <version>18.4</version>
</dependency>

<dependency>
    <groupId>org.geotools</groupId>
    <artifactId>gt-geojson</artifactId>
    <version>18.4</version>
</dependency>


<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongodb-driver</artifactId>
    <version>3.6.2</version>
</dependency>

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.2</version>
</dependency>


1. 统一返回结果封装
/**
 * @program: tool
 * @description:
 * @author: Mr.superbeyone
 * @create: 2018-10-18 16:37
 **/
@Data
public class JsonResult<T> {
    private Integer code;
    private String msg;
    private T data;

    //使用 lombok @Data注解 或者  Get Set方法 ...
}
2. shp文件数据实体封装
/**
 * @program: tool
 * @description:
 * @author: Mr.superbeyone
 * @create: 2018-10-16 12:12
 **/
@Data
public class ShapeModel implements Serializable {
    private String id;
    private String type;
    private String geometry;
    private String properties;
    //使用 lombok @Data注解 或者  Get Set方法 ...
}
3. 核心代码
/**
  * 读取shp文件
  *
  * @param filePath   读取的文件路径
  * @param collection mongoDB collection
  * @return
  */
private JsonResult<Set<String>> readShapeFile(String filePath, MongoCollection<Document> collection) {
        JsonResult<Set<String>> result = new JsonResult<>();
        Set<String> set = new HashSet<>();
        File folder = new File(filePath);
        if (!folder.isDirectory()) {
            if (folder.toString().endsWith(".shp")) {
                try {
                    return getShapeFile(folder, collection);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                System.out.println("选择的文件后缀名不是.shp");
                return null;
            }
        } else {
            File[] files = folder.listFiles();
            if (files.length <= 0) {
                System.out.println("目录文件为空");
                return null;
            }

            for (File file : files) {
                if (!file.toString().endsWith(".shp")) {
                    continue;
                }
                try {
                    result = getShapeFile(file, collection);
                    Set fields = result.getData();
                    set.addAll(fields);
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
            result.setData(set);
        }

        return result;
    }





private JsonResult<Set<String>> getShapeFile(File file, MongoCollection<Document> collection) {
        JsonResult<Set<String>> result = new JsonResult();
        HashSet<String> fields = new HashSet<>();
        int number = 0;
        int index = 0;
        try {
            ShapefileDataStore shapefileDataStore = new ShapefileDataStore(file.toURI().toURL());
            shapefileDataStore.setCharset(Charset.forName("utf-8"));
            ContentFeatureSource featureSource = shapefileDataStore.getFeatureSource();
            SimpleFeatureIterator featureIterator = featureSource.getFeatures().features();
            ArrayList<Document> documents = new ArrayList<>();
            Document document = null;
            while (featureIterator.hasNext()) {

                number++;
                SimpleFeature feature = featureIterator.next();
                Collection<? extends Property> properties = feature.getValue();
                //feature转GeoJSON
                FeatureJSON featureJSON = new FeatureJSON();
                StringWriter writer = new StringWriter();
                featureJSON.writeFeature(feature, writer);
				//TODO: 判断writer.toString().length() 否则可能会抛下列异常
				//org.bson.BsonSerializationException: Payload document size of is larger than maximum of 16777216

                ShapeModel shapeModel = JSON.parseObject(writer.toString(), ShapeModel.class);
                document = new Document();

                
                if (properties.size() < 0) {
                    continue;
                }
                if (index == 0) {
                    for (Property property : properties) {
                        if (property.getType().getClass() == org.geotools.feature.type.AttributeTypeImpl.class) {
                            fields.add(property.getName().toString());
                        } else {
                        	//空间字段
                            fields.add("#" + property.getName() + "#");
                        }
                    }
                    
                    result.setData(fields);
                    result.setCode(ResultCodeEnum.GET_UPDATE_FILE_FIELDS_SUCCESS.getCode());
                    result.setMsg(ResultCodeEnum.GET_UPDATE_FILE_FIELDS_SUCCESS.getMsg());

                    //TODO:创建分片数据库
                    //createShardDatabase(fields);
                }
                
                for (Property property : properties) {
                    if (property.getType().getClass() == org.geotools.feature.type.AttributeTypeImpl.class) {
                        if (property.getValue() == null) {
                            document.put(property.getName().toString(), "");
                        } else {
                            document.put(property.getName().toString(), property.getValue().toString());
                        }

                    } else {
                    	//空间字段
                        document.put(property.getName().toString(), shapeModel.getGeometry());
                    }
                }
                
                index++;
                //逐条插入
               //collection.insertOne(document);
                documents.add(document);

				//每1000条数据插入一次
                if (number % 1000 == 0) {
                    collection.insertMany(documents);
                    documents = new ArrayList<>();
                }
                //最后插入不足1000条的数据
                if (!featureIterator.hasNext()) {
                    collection.insertMany(documents);
                }

            }
        } catch (Exception e) {
            //出现异常
            result.setMsg("插入第" + (index + 1) + "条时出现错误");
            result.setCode(4000);            
        } finally {
        	featureIterator.close();
        }

        return result;
    }
}
3. 可能出现的异常
org.bson.BsonSerializationException: Payload document size of is larger than maximum of 16777216
3.1 异常产生原因
  • 当前插入的数据大于16M,会抛出此异常
3.2 解决方案
  • 判断所要插入的数据的大小,如果大于16M,可以选择跳过,或者停止插入
4 扩展
4.1 创建数据库分片
public void createShardDatabase(Set<String> fields) {

        //TODO:使用 databaseName 生成策略
        String databaseName = "super";
        //TODO:使用 collectionName 生成策略
        String collectionName = "beyone";


        List<String> set = new ArrayList<>();

        Map<String, Object> map = new HashMap<String, Object>();


        if (fields.size() < 0) {
            return;
        }
        for (String field : fields) {
        	//空间字段
            if (field.startsWith("#") && field.endsWith("#")) {
                String splitField = field.split("#")[1];
                map.put(splitField, "hashed");
            } else {
                set.add(field);
            }
        }
		//mongoDBConfig 是通过注入获得的
		/**
		 * @Autowired
		 * MongoDBConfig mongoDBConfig;
		 */
        MongoClient client = new MongoClient(mongoDBConfig.getHost(), mongoDBConfig.getPort());
        MongoDatabase adminDB = client.getDatabase(mongoDBConfig.getDatabase());
        Document enableShardDoc = new Document();
        enableShardDoc.put("enablesharding", databaseName);
        Document result = adminDB.runCommand(enableShardDoc);
        Object obj = result.get("ok");
        if (null == obj) {
        }
        if ("1.0".equals(obj.toString())) {
            Document shardKeyDoc = new Document();
            String coll = databaseName + "." + collectionName;
            shardKeyDoc.put("shardcollection", coll);
            Document t = new Document();
            t.putAll(map);
            shardKeyDoc.put("key", t);
            result = adminDB.runCommand(shardKeyDoc);
            obj = result.get("ok");
            if (null == obj) {

                //logger.info("error");
            }
            if ("1.0".equals(obj.toString())) {
                //logger.info("success");

            } else {
                //logger.info("error");
            }
        } else {
            //logger.info("error");
        }

    }

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Java中,要读取shapefile zip文件,可以使用GeoTools库来实现。GeoTools是一个开源的地理空间数据处理库,提供了丰富的功能和API来进行地理空间数据的读取和处理。 首先,需要导入GeoTools的相关库文件。可以通过Maven将GeoTools库添加到项目中,具体的依赖信息可以参考GeoTools官方网站。 接下来,需要创建一个ShapefileDataStore对象,用于读取shapefile文件。可以通过如下代码实现: ```java File zipFile = new File("path/to/shapefile.zip"); Map<String, Serializable> params = new HashMap<>(); params.put("url", zipFile.toURI().toURL()); DataStore dataStore = DataStoreFinder.getDataStore(params); ``` 然后,可以使用DataStore对象来获取shapefile文件中的图层信息,并通过FeatureSource对象来获取特征(Feature)。如下所示: ```java String[] typeNames = dataStore.getTypeNames(); String typeName = typeNames[0]; // 获取第一个图层的名称 FeatureSource<SimpleFeatureType, SimpleFeature> featureSource = dataStore.getFeatureSource(typeName); ``` 最后,可以通过FeatureIterator循环遍历shapefile文件中的特征数据,并进行相应的处理。例如,可以获取特征的属性信息、几何信息等。如下所示: ```java try (FeatureIterator<SimpleFeature> iterator = featureSource.getFeatures().features()) { while (iterator.hasNext()) { SimpleFeature feature = iterator.next(); // 获取属性信息 Collection<Property> properties = feature.getProperties(); for (Property property : properties) { String name = property.getName().toString(); Object value = property.getValue(); // 处理属性信息... } // 获取几何信息 Geometry geometry = (Geometry) feature.getDefaultGeometry(); // 处理几何信息... } } ``` 综上所述,以上就是使用Java读取shapefile zip文件的基本步骤。通过使用GeoTools库,可以轻松地读取和处理shapefile文件的数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

superbeyone

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值