GeoTools:FeatureShapefile之CRUD操作

news2024/11/29 20:48:11

        之前在《GIS开源框架:ArcGIS文件地理数据库(GDB)解析与入库》中,从地理数据库的角度对Feature要素进行了解释,接下来,我们将从GeoTools库的角度,重新认识Feature要素,并通过GeoTools实现Shapefile文件在Feature要素层面的CRUD操作。

目录

Feature要素

FeatureClass要素类

Geometry

DataStore数据源

读取Shapefile文件

添加Feature到Shapefile文件中

修改Shapefile文件中的Feature要素属性

删除Shapefile文件中的Feature要素


Feature要素

        所谓Feature要素,实质上就是在map地图上展示出来的东西。严格意义上讲:Feature要素是对现实世界客观实体的抽象表达。

        但是对于Java开发者而言,最简明的解释就是:一个Feature就是一个对象。像Java对象一样,Feature要素可以用于表达客观实体与现实世界相关的信息。这些信息将被组织成attributes属性,然后被写入field字段中保存。

        有时候,对于两个拥有共性的Feature要素,我们就可以对其进行抽象——转为用一个Class类来描述这一类要素。例如:对于两个机场A、B,我们可以创建一个Airport类来描述其公共属性,但是在Map地图上,我们将创建一个FeatureType来进行表达。

         那么,如何来概括Java和Map地图之间的关系呢?我们可以通过下表进行理解,

FeatureClass要素类

        GeoTools中,通过GeoAPI项目提供了Feature、FeatureType、Attribute接口。通常地,GeoAPI提供了十分严格的接口,而GeoTools提供了对应的class类。

         对于一个Feature要素来讲,仅仅有一些简单属性Attributes(例如:String、Integer、Date等类型的)是十分常见的。为了满足这种需求,GeoTools提供了SimpleFeature子类。

Geometry

        Object对象和Feature要素之间的另一个不同之处是:Feature包含一些位置信息。这些位置信息可以通过Geometry几何图形进行收集,并作为Attribute属性字段保存。

         GeoTools提供了 JTS Topology Suite(JTS)模块来描述Geometry几何图形,基于JTS,可以实现对于任何几何图形数据的高效处理操作。

        以下为使用JTS库,基于Well-Known-Text (WKT)格式创建Point点的示例代码,

    @Test
    public void crateGeometryFromWKT() throws  ParseException {
        GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory( null );
        WKTReader reader = new WKTReader( geometryFactory );
        Point point = (Point) reader.read("POINT (1 1)");
        System.out.println(point);
    }

         以下为直接使用GeometryFactory工厂类创建Point的示例代码,

    @Test
    public void crateGeometryByGeometryFactory() throws  ParseException {
        GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory( null );
        Coordinate coordinate = new Coordinate(1,1);
        Point point = geometryFactory.createPoint(coordinate);
        System.out.println(point);
    }

DataStore数据源

        GeoTools提供了DataStore接口,用于表示一个包含空间数据(spatial data)的File文件、DataBase数据库、Service服务——即:空间数据源。API结构如下所示,

         FeatureSource被用于读取数据源中的Feature要素数据,其子类FeatureStore拥有对数据源的读写权限。

读取Shapefile文件

         例如:读取上图所示的out.shp文件中的要素数据示例代码如下,

@Test
    public void readShapefile() throws IOException {
        String filePath = "C:\\Users\\13241\\Documents\\data\\out.shp";
        File file = new File(filePath);
        DataStore dataStore = new ShapefileDataStore(file.toURI().toURL());//创建ShapefileDataStore实例
        String[] typeNames = dataStore.getTypeNames();//获取数据源中所有可获取的图层名称
        System.out.println(Arrays.toString(typeNames));
        //逐个解析图层数据
        for (int i = 0; i < typeNames.length; i++) {
            String typeName = typeNames[i];
            //获取FeatureSource
            SimpleFeatureSource featureSource = dataStore.getFeatureSource(typeName);
            SimpleFeatureCollection features = featureSource.getFeatures();//获取FeatureSource中的Feature集合
            SimpleFeatureIterator iterator = features.features();//获取集合迭代器
            while (iterator.hasNext()){
                SimpleFeature next = iterator.next();
                SimpleFeatureType featureType = next.getFeatureType();
                List<AttributeDescriptor> attributeDescriptors = featureType.getAttributeDescriptors();
                for (int i1 = 0; i1 < attributeDescriptors.size(); i1++) {
                    Name name = attributeDescriptors.get(i1).getName();
                    System.out.print(name+":"+next.getAttribute(name)+"\t");
                }
                Object defaultGeometry = next.getDefaultGeometry();
                System.out.println();
            }
        }
    }

添加Feature到Shapefile文件中

执行添加操作之前的out.shp

         添加Feature到Shapefile文件中的示例代码如下,

  @Test
    public void addFeaturesToShp() throws SchemaException, IOException {
        //Geometry工厂类
        GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
        /*
         * FeatureType-定义Feature的字段结构
         * TYPE is used as a template to describe the file contents
         */
        final SimpleFeatureType TYPE = DataUtilities.createType(
                "Location",
                "the_geom:Point:srid=4326,"
                        + // <- the geometry attribute: Point type
                        "name:String,"
                        + // <- a String attribute
                        "number:Integer" // a number attribute
        );
        String name = "dsandjkadmskladakndsaldmalkdmaldkas";
        Random random = new Random();
        //创建10个新的Feature要素-[带有属性信息的简单Feature-SimpleFeature]
        List<SimpleFeature> features = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
            Point point = geometryFactory.createPoint(new Coordinate(120.0+Math.random(),32.0+Math.random()));
            //注意字段添加顺序
            featureBuilder.add(point);
            featureBuilder.add(name.substring(0,random.nextInt(name.length())));
            featureBuilder.add(10+random.nextInt(20));
            SimpleFeature simpleFeature = featureBuilder.buildFeature(null);//创建Feature实例
            features.add(simpleFeature);
        }
        //向shp文件中添加新的Feature要素
        SimpleFeatureCollection collection = new ListFeatureCollection(TYPE,features);
        //获取Shapefile数据源
        String filePath = "C:\\Users\\13241\\Documents\\data\\out.shp";
        File file = new File(filePath);
        DataStore dataStore = new ShapefileDataStore(file.toURI().toURL());//创建ShapefileDataStore实例
        SimpleFeatureSource featureSource = dataStore.getFeatureSource("out");//获取FeatureSource
        if( featureSource instanceof SimpleFeatureStore){
            SimpleFeatureStore store = (SimpleFeatureStore) featureSource; // write access!
            store.addFeatures(collection);
        }
    }

        添加之后,可以看到out.shp文件中共计为25个Feature要素。

执行添加操作之后的out.shp

修改Shapefile文件中的Feature要素属性

        可以看到,上面执行完添加操作之后的out.shp属性表中某些记录的name属性为null。下面,我们执行更新操作,将name=null的记录进行修改——统一将name属性修改为xxx。

        考虑到name属性值可能为null,也可能为空白字符串。因此,先通过Filter过滤器,获取到对应的记录,示例代码如下,

    @Test
    public void modifyFeatureFromShp() throws IOException, CQLException {
        //获取数据源
        String filePath = "C:\\Users\\13241\\Documents\\data\\out.shp";
        File file = new File(filePath);
        DataStore dataStore = new ShapefileDataStore(file.toURI().toURL());//创建ShapefileDataStore实例
        SimpleFeatureSource featureSource = dataStore.getFeatureSource("out");//获取FeatureSource
        if( featureSource instanceof SimpleFeatureStore){
            SimpleFeatureStore store = (SimpleFeatureStore) featureSource; // write access!
//            store.modifyFeatures("name", "xxx", CQL.toFilter("name is null"));
            Filter filter = CQL.toFilter("name = '' OR name IS NULL");
//            Query query = new Query(filter);
            SimpleFeatureCollection features = featureSource.getFeatures(filter);
            SimpleFeatureIterator iterator = features.features();
            System.out.println(features.size());
            while (iterator.hasNext()) {
                SimpleFeature next = iterator.next();
                SimpleFeatureType featureType = next.getFeatureType();
                List<AttributeDescriptor> attributeDescriptors = featureType.getAttributeDescriptors();
                for (int i1 = 0; i1 < attributeDescriptors.size(); i1++) {
                    Name name = attributeDescriptors.get(i1).getName();
                    System.out.print(name + ":" + next.getAttribute(name) + "\t");
                }
                System.out.println();
            }
        }
    }

        获取结果如下,

         接着,我们继续使用同样的Filter过滤器,将目标记录的name字段值改为xxx。示例代码如下,

  //根据条件修改记录
    @Test
    public void modifyFeatureFromShp() throws IOException, CQLException {
        //获取数据源
        String filePath = "C:\\Users\\13241\\Documents\\data\\out.shp";
        File file = new File(filePath);
        DataStore dataStore = new ShapefileDataStore(file.toURI().toURL());//创建ShapefileDataStore实例
        SimpleFeatureSource featureSource = dataStore.getFeatureSource("out");//获取FeatureSource
        if( featureSource instanceof SimpleFeatureStore){
            SimpleFeatureStore store = (SimpleFeatureStore) featureSource; // write access!
//            store.modifyFeatures("name", "xxx", CQL.toFilter("name is null"));
            Filter filter = CQL.toFilter("name = '' OR name IS NULL");
            store.modifyFeatures("name","xxx",filter);
        }
    }

        再次查看属性表,可以看到name为空的记录已经被修改成功,

 

删除Shapefile文件中的Feature要素

        接下来,我们尝试将name='xxx‘的Feature删除掉,示例代码如下,

    //根据条件删除记录
    @Test
    public void deleteFeatureFromShp() throws IOException, CQLException {
        //获取数据源
        String filePath = "C:\\Users\\13241\\Documents\\data\\out.shp";
        File file = new File(filePath);
        DataStore dataStore = new ShapefileDataStore(file.toURI().toURL());//创建ShapefileDataStore实例
        SimpleFeatureSource featureSource = dataStore.getFeatureSource("out");//获取FeatureSource
        if( featureSource instanceof SimpleFeatureStore){
            SimpleFeatureStore store = (SimpleFeatureStore) featureSource; // write access!
//            store.modifyFeatures("name", "xxx", CQL.toFilter("name is null"));
            Filter filter = CQL.toFilter("name = 'xxx'");
            store.removeFeatures(filter);
        }
    }

        可以看到,我们总的Feature要素数量已经由25变为23,并且目标Feature要素也已经被删除掉。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/344664.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

产品、技术:如何编写有效的流程文档?

流程文档是指一系列的、连续的、有规律的活动过程&#xff0c;而这些活动以特定的方式进行&#xff0c;并导致特定结果&#xff08;创造价值&#xff09;的产生。流程梳理是指围绕企业的内部要素与外部要素&#xff0c;对整个企业的业务特点和现状进行深入细致的分析、整理、提…

Fiddler使用笔记(柠檬班)

Fiddler笔记 内部功能 Replay 重放请求。 号 移除请求&#xff0c;可以通过Shift Delete来选择要保存的请求&#xff0c;其他的都删掉。 Go 断点的时候使用&#xff0c;作用是转到下一步。 Stream 流模式&#xff0c;一般不用它。 Decode 用于解码信息。通常对响应…

Ambire AdEx 2023 年路线图

Ambire AdEx 是为简化 web3 显示广告而建立的&#xff0c;领先于时代。到 2023 年&#xff0c;它将专注于服务用户需求&#xff0c;同时保持其作为区块链隐私解决方案的核心&#xff0c;反对传统的数字广告模式。 回顾 2022 年 2022 年&#xff0c;AdEx 网络处理了超过 1 亿次展…

Hudi-并发控制

并发控制 Hudi支持的并发控制 MVCC Hudi的表操作&#xff0c;如压缩、清理、提交&#xff0c;hudi会利用多版本并发控制来提供多个表操作写入和查询之间的快照隔离。使用MVCC这种模型&#xff0c;Hudi支持并发任意数量的操作作业&#xff0c;并保证不会发生任何冲突。Hudi默…

小米电视安装 Plex 打造家庭影院

背景 最近突然想重温教父&#xff0c;本来想着直接投屏就可以&#xff0c;后来看了别人搭建的基于 NAS 的家庭影院很动心&#xff0c;也想依葫芦画瓢做一个&#xff0c;跟对象申请经费的时候被拒了&#xff0c;理由是有这钱还不如开个会员直接看。 我寻思不同电影在不同的平台…

遥感反演叶面积指数 (LAI)

叶面积指数 叶面积指数&#xff08;Leaf Area Index, LAI&#xff09;是反映一个生态系统中单位面积上的叶面积综合的一半&#xff0c;是模拟陆地生态过程、水热循环和生物地球化学循环的重要参数。 本文主要介绍LAI的遥感反演方法&#xff0c;其主要分为统计方法、植被辐射传输…

传奇私服搭建网站的几种方法

搭建网站的几种方法&#xff1a;一些人&#xff0c;连简单的搭建网站都不会&#xff0c;还要请技术帮忙&#xff0c;真是牛B&#xff0c;这里简单介绍下几种办法一&#xff1a;2003系统下&#xff0c;直接使用IIS&#xff0c;这个太简单了&#xff0c;桌面上就有IIS&#xff0c…

权威报告!这五个消费趋势,告诉你如何抓住中国消费者的心和钱包

有人说2023年是消费复苏的一年&#xff0c;市场回暖趋势明显&#xff1b;也有人说之前的亏空太大&#xff0c;想要短时间追上来不太可能&#xff0c;因此2023的消费市场最多是不低迷&#xff0c;达不到火热。这可把做生意的各位老板整纠结了&#xff0c;究竟今年要不要投个大手…

mysql 跳过事务 gtid

企业生产场景mysql主从复制故障原因 企业生产场景mysql主从复制故障原因 实验一&#xff1a; 目的&#xff1a;解决主从不同步&#xff08;本例中sql线程出现问题&#xff09; 方法&#xff1a;模拟故障场景 1.在SLAVE上建立一个名为yingying数据库。…

Webstorm 代码没有提示,uniapp 标签报错

问题 项目是用脚手架创建的&#xff1a; vue create -p dcloudio/uni-preset-vue my-project 打开之后&#xff0c;添加view标签警告报错的。代码也没有提示&#xff0c;按官方说法&#xff1a;CLI 工程默认带了 uni-app 语法提示和 5App 语法提示。 但是我这里就是有问题。…

Oracle实现高可用性的工具(负载均衡/故障切换)

Oracle实现高可用性的工具&#xff08;负载均衡/故障切换&#xff09;1 Oracle RAC故障转移负载均衡2 Data Guard负载均衡-读写分离Data Guard Broker3 GDSGSM&#xff1a;连接管理工具主要功能Data Guard Broker功能是监控Data Guard状态&#xff0c;当主库异常时自动切换角色…

idea2021版本新建maven项目

首先我们需要下载maven版本(maven下载地址Maven – Download Apache Maven)&#xff0c;并且配置好maven仓库与环境变量&#xff0c;这里不细述了。打开idea选择新建项目&#xff0c;选择maven&#xff0c;效果如下图 我们选择maven-archetype-webapp类型。 下一步&#xff0c;…

4.9 内部类

文章目录1.内部类概述2.特点3.练习 : 内部类入门案例4.成员内部类4.1 练习 : 被private修饰4.2 练习 : 被static修饰5.局部内部类6.匿名内部类1.内部类概述 如果一个类存在的意义就是为指定的另一个类&#xff0c;可以把这个类放入另一个类的内部。 就是把类定义在类的内部的情…

MQ中间件概念一览

一、概述 1. 大多应用中&#xff0c;可通过消息服务中间件来提升系统异步通信、扩展解耦能力 2. 消息服务中两个重要概念&#xff1a; 消息代理&#xff08;message broker&#xff09;和目的地&#xff08;destination&#xff09; 当消息发送者发送消息以后&#xff0c;将由…

有了ChatGPT 微软对元宇宙不香了?

押注ChatGPT是微软最近的主要发力点&#xff0c;另一边&#xff0c;它开始向元宇宙业务挥出裁员“大刀”。海外消息称&#xff0c;微软解散了成立仅四个月的工业元宇宙团队&#xff0c;约100名员工被全被解雇。 这只是微软放缓元宇宙战略的长尾动作&#xff0c;此前&#xff0…

【MFC】模拟采集系统——界面设计(17)

功能介绍 启动界面 开始采集&#xff1a; PS&#xff1a;不涉及 数据保存&#xff0c;重现等功能 界面设计 界面分为三块&#xff1a;顶部黑条带关闭按钮、左边对话框&#xff0c;右边的主界面 资源&#xff1a; 顶部黑条 top.bmp 2* 29 &#xff08;宽 * 高 像素点&…

SAS应用入门学习笔记7

代码说明&#xff1a; 1&#xff09;distinct 想获得region变量有的多少种&#xff1f; 2&#xff09;如果是常规语句&#xff0c;我们是使用proc freq 语句&#xff1a; where for filter&#xff1a; 然后有一个escape语句的概念&#xff1a; 这是一个简单的语法&#xff…

Redis集群离线安装

近日&#xff0c;由于客户的系统运行环境在一个封闭的网络内&#xff0c;不能与互联网联通&#xff0c;也不能提供yum库&#xff0c;所以运行环境只能采用离线安装的方式&#xff0c;我总结了一下本次的安装经过&#xff0c;希望对需要的人有所帮助。一、安装gcc查看gcc版本要求…

牛客网Python篇数据分析习题(五)

1.现有牛客网12月每天练习题目的数据集nowcoder.csv。包含如下字段&#xff08;字段之间用逗号分隔&#xff09;&#xff1a; user_id:用户id question_id&#xff1a;问题编号 result&#xff1a;运行结果 date&#xff1a;练习日期 请你统计答对和答错的总数分别是多少。 imp…

态路小课堂丨下一代数据中心100G接口第二篇——SFP-DD封装

100G光模块根据封装模式可分为QSFP28、CXP、CFP、CFP2、FCP4、DSFP和SFP-DD等。态路小课堂之前已经大量介绍了相关内容&#xff08;。 态路小课堂丨下一代数据中心100G接口——DSFP态路小课堂丨100G解决方案-425G NRZ光模块态路小课堂丨什么是100G QSFP28单波光模块&#xff1f…