Spring-Boot ? ShapeFile文件读写工具类+接口调用

一、项目目录结构树

二、项目启动

三、往指定的shp文件里写内容

(1) json数据【Post】

{
    "name":"test",
    "path":"c:/test",
    "geom":"MULTIPOLYGON(((101.870371 25.19228,101.873633 25.188183,101.880564 25.184416,101.886808 25.186028,101.892043 25.189969,101.896592 25.190163,101.903716 25.190785,101.905454 25.193464,101.899897 25.196202,101.894146 25.197911,101.891657 25.19826,101.886078 25.197658,101.884211145538 25.2007060137013,101.88172564506 25.1949712942389,101.87874 25.199619,101.874641 25.200998,101.868547 25.202415,101.863741 25.202415,101.85887 25.202842,101.854557 25.202182,101.852604 25.199736,101.852282 25.19628,101.854492 25.194183,101.855608 25.192668,101.863698 25.192105,101.870371 25.19228)))",
    "id":1001,
    "des":"湖泊水面"

}

(2)接口调用

(3)QGIS查看,验证数据有效性

四、读取指定shp文件,并显示内容

(1)接口调用

(2)QGIS显示北京故宫【shp文件在项目中的static文件夹下】

五、将指定的shp文件转成image文件或流

(1) 接口调用  === 转image【png】文件

c盘下查看

(2) 接口调用  === 转image流,输出到客户端

六、核心工具类【ShpTools】

package com.appleyk.geotools;

import com.appleyk.IO.StringTokenReader;
import com.appleyk.pojos.ShpDatas;
import com.appleyk.pojos.ShpInfo;
import com.appleyk.result.ResponseMessage;
import com.appleyk.result.ResponseResult;
import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
import org.geotools.data.*;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.map.FeatureLayer;
import org.geotools.map.Layer;
import org.geotools.map.MapContent;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.renderer.lite.StreamingRenderer;
import org.geotools.styling.SLD;
import org.geotools.styling.Style;
import org.geotools.swing.JMapFrame;
import org.geotools.swing.data.JFileDataStoreChooser;
import org.opengis.feature.Property;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.springframework.util.ResourceUtils;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>shapefile读写工具类</p>
 * @author Appleyk
 * @blob https://blog.csdn.net/appleyk
 * @date Created on 上午 11:54 2018-10-12
 */
public class ShpTools {

    /**
     * 集合对象构造器【自定义的】
     */
    private  static GeometryCreator gCreator = GeometryCreator.getInstance();

    /**
     * 边界
     */
    private  static ReferencedEnvelope bounds;

    // 画布的宽度
    private static final int IMAGE_WIDTH = 2400;

    // 画布的高度
    private static final int IMAGE_HEIGHT = 1200;

    /**
     * 通过shp文件路径,读取shp内容
     * @param filePath
     * @throws Exception
     */
    public static ShpDatas readShpByPath(String filePath,Integer limit) throws Exception {

        // 一个数据存储实现,允许从Shapefiles读取和写入
        ShapefileDataStore shpDataStore =  new ShapefileDataStore(new File(filePath).toURI().toURL());
        // 设置编码【防止中文乱码】
        shpDataStore.setCharset(Charset.forName("UTF-8"));

        // getTypeNames:获取所有地理图层,这里我只取第一个【如果是数据表,取出的就是表名】
        String typeName = shpDataStore.getTypeNames()[0];
        System.out.println("shp【图层】名称:"+typeName);
        FeatureCollection<SimpleFeatureType, SimpleFeature> result = getFeatures(shpDataStore, typeName);

        // 迭代特征集合
        FeatureIterator<SimpleFeature> iterator = result.features();

        ShpDatas shpDatas = new ShpDatas();
        shpDatas.setName(typeName);
        shpDatas.setShpPath(filePath);
        buildShpDatas(limit, iterator, shpDatas);
        iterator.close();
        return  shpDatas;
    }

    /**
     * 根据数据源及图层名称拿到特征集合
     * @param shpDataStore
     * @param typeName
     * @return
     * @throws IOException
     */
    private static FeatureCollection<SimpleFeatureType, SimpleFeature> getFeatures(ShapefileDataStore shpDataStore, String typeName) throws IOException {

        // 通过此接口可以引用单个shapefile、数据库表等。与数据存储进行比较和约束
        FeatureSource<SimpleFeatureType, SimpleFeature> featureSource = shpDataStore.getFeatureSource(typeName);
        // 一个用于处理FeatureCollection的实用工具类。提供一个获取FeatureCollection实例的机制
        FeatureCollection<SimpleFeatureType, SimpleFeature> result = featureSource.getFeatures();
        System.out.println("地理要素【记录】:"+result.size()+"个");
        System.out.println("==================================");
        return result;
    }

    /**
     * 构建shpDatas对象
     * @param limit
     * @param iterator
     * @param shpDatas
     */
    private static void buildShpDatas(Integer limit, FeatureIterator<SimpleFeature> iterator, ShpDatas shpDatas) {
        // 这里我们只迭代前limit个
        int stop = 0;
        while (iterator.hasNext()) {
            if (stop > limit) {
                break;
            }
            // 拿到一个特征
            SimpleFeature feature = iterator.next();
            // 取出特征里面的属性集合
            Collection<Property> p = feature.getProperties();

            // 遍历属性集合
            Map<String,Object> prop = new HashMap<>();
            for (Property pro : p) {
                String key = pro.getName().toString();
                String val = pro.getValue().toString();
                prop.put(key, val);
                System.out.println("key【字段】:"+key+"\t||  value【值】:"+val);
            }
            System.out.println("\n============================ 序号:"+stop+"\n");
            shpDatas.addProp(prop);
            stop++;
        } // end 最外层 while
    }

    /**
     * 将一个几何对象写进shapefile
     * @param filePath
     * @param geometry
     */
    public  static  void writeShpByGeom(String filePath, Geometry geometry) throws Exception{

        ShapefileDataStore ds = getshpDS(filePath, geometry);

        FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(ds.getTypeNames()[0],
                Transaction.AUTO_COMMIT);

        // Interface SimpleFeature:一个由固定列表值以已知顺序组成的SimpleFeatureType实例。
        SimpleFeature feature = writer.next();
        feature.setAttribute("name", "XXXX名称");
        feature.setAttribute("path", "c:/test");
        feature.setAttribute("the_geom", geometry);
        feature.setAttribute("id", 1010L);
        feature.setAttribute("des", "XXXX描述");

        System.out.println("========= 写入【"+geometry.getGeometryType()+"】成功 !=========");

        // 写入
        writer.write();

        // 关闭
        writer.close();

        // 释放资源
        ds.dispose();

    }

    /**
     * 将一个几何对象写进shapefile
     * @param shpInfo
     */
    public  static ResponseResult writeShpByGeom(ShpInfo shpInfo) throws Exception{

        // 特殊字符串解析器
        StringTokenReader reader = new StringTokenReader();
        // 根据几何对象的wkt字符串,反解【解析】成Geometry对象
        Geometry geometry = reader.read(shpInfo.getGeom());
        // 拿到shp对象所在的目录【文件夹】
        String path = shpInfo.getPath();
        File file = new File(path);
        if(!file.exists()){
            file.mkdir();
        }

        if(!file.isDirectory()){
            return  new ResponseResult(ResponseMessage.BAD_REQUEST,"path不是有效的文件夹" );
        }

        String filePath = shpInfo.getPath()+"/"+shpInfo.getName()+".shp";
        ShapefileDataStore ds = getshpDS(filePath, geometry);
        String typeName = ds.getTypeNames()[0];
        FeatureWriter<SimpleFeatureType, SimpleFeature> writer ;
        if(shpInfo.isAppendWrite()){
            // 追加写几何对象
            writer = ds.getFeatureWriterAppend(typeName, Transaction.AUTO_COMMIT);
        }else{
            // 覆盖写几何对象
            writer = ds.getFeatureWriter(typeName, Transaction.AUTO_COMMIT);
        }

        // Interface SimpleFeature:一个由固定列表值以已知顺序组成的SimpleFeatureType实例。
        SimpleFeature feature = writer.next();
        feature.setAttribute("name", shpInfo.getName());
        feature.setAttribute("path", shpInfo.getPath());
        feature.setAttribute("the_geom", geometry);
        feature.setAttribute("id", shpInfo.getId());
        feature.setAttribute("des", shpInfo.getDes());

        System.out.println("========= 写入【"+geometry.getGeometryType()+"】成功 !=========");

        // 写入
        writer.write();

        // 关闭
        writer.close();

        // 释放资源
        ds.dispose();

        // 返回创建成功后的shp文件路径
        return  new ResponseResult(ResponseMessage.OK,filePath);

    }

    /**
     * 拿到配置好的DataStore
     * @param filePath
     * @param geometry
     * @return
     * @throws IOException
     */
    private static ShapefileDataStore getshpDS(String filePath, Geometry geometry) throws IOException {
        // 1.创建shape文件对象
        File file = new File(filePath);

        Map<String, Serializable> params = new HashMap<>();

        // 2、用于捕获参数需求的数据类 URLP:url to the .shp file.
        params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL());

        // 3、创建一个新的数据存储【如果存在,则不创建】
        ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);

        // 4、定义图形信息和属性信息 -- SimpleFeatureTypeBuilder 构造简单特性类型的构造器
        SimpleFeatureTypeBuilder tBuilder = new SimpleFeatureTypeBuilder();

        // 5、设置 -- WGS84:一个二维地理坐标参考系统,使用WGS84数据
        tBuilder.setCRS(DefaultGeographicCRS.WGS84);
        tBuilder.setName("shapefile");

        // 添加名称
        tBuilder.add("name", String.class);
        // 添加shp所在目录名称
        tBuilder.add("path", String.class);
        // 添加 一个几何对象
        tBuilder.add("the_geom", geometry.getClass());
        // 添加一个id
        tBuilder.add("id", Long.class);
        // 添加描述
        tBuilder.add("des", String.class);

        // 设置此数据存储的特征类型
        ds.createSchema(tBuilder.buildFeatureType());

        // 设置编码
        ds.setCharset(Charset.forName("UTF-8"));
        return ds;
    }

    /**
     * 打开shp文件,获取地图内容
     * @param filePath  文件路径
     * @param isOpenByChoose 是否自定义打开shp文件
     * @throws Exception
     */
    public static  MapContent getMapContentByPath(String filePath,boolean isOpenByChoose,String color) throws  Exception{

        File file;
        if(isOpenByChoose){
            // 1.1、 数据源选择 shp扩展类型的
            file = JFileDataStoreChooser.showOpenFile("shp", null);
        }else{
            // 1.2、根据路径拿到文件对象
            file = new File(filePath);
        }

        if(file==null){
            return null;
        }
        // 2、得到打开的文件的数据源
        FileDataStore store = FileDataStoreFinder.getDataStore(file);

        // 3、设置数据源的编码,防止中文乱码
        ((ShapefileDataStore)store).setCharset(Charset.forName("UTF-8"));

        /**
         * 使用FeatureSource管理要素数据
         * 使用Style(SLD)管理样式
         * 使用Layer管理显示
         * 使用MapContent管理所有地图相关信息
         */

        // 4、以java对象的方式访问地理信息 --    简单地理要素
        SimpleFeatureSource featureSource = store.getFeatureSource();

        bounds = featureSource.getBounds();

        // 5、创建映射内容,并将我们的shapfile添加进去
        MapContent mapContent = new MapContent();

        // 6、设置容器的标题
        mapContent.setTitle("Appleyk‘s GeoTools");

        Color color1;
        if(color == null || "".equals(color)){
            color1 = Color.BLACK;
        }else if("red".equals(color)){
            color1 = Color.RED;
        }else if("green".equals(color)){
            color1 = Color.GREEN;
        }else if("blue".equals(color)){
            color1 = Color.BLUE;
        }else{
            color1 = Color.ORANGE;
        }

        // 7、创建简单样式 【颜色填充】
        Style style = SLD.createSimpleStyle(featureSource.getSchema(),color1);

        // 8、显示【shapfile地理信息+样式】
        Layer layer = new FeatureLayer(featureSource, style);

        // 9、将显示添加进map容器
        mapContent.addLayer(layer);

        return  mapContent;
    }

    public  static  void showMap(MapContent mapContent){
        JMapFrame.showMap(mapContent);
    }

    /**
     * shp文件转Image【格式定png】
     * @param shpFilePath shp目标文件
     * @param destImagePath 转成图片的文件 == 如果没有,转成的图片写进response输出流里
     * @param response 响应流
     * @throws Exception
     */
    public static void shp2Image(String shpFilePath,String destImagePath,String color, HttpServletResponse response) throws  Exception{

        // 流渲染器
        StreamingRenderer renderer = new StreamingRenderer();
        MapContent mapContent = getMapContentByPath(shpFilePath,false,color );
        renderer.setMapContent(mapContent);
        Rectangle imageBounds = new Rectangle(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
        BufferedImage dumpImage = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = dumpImage.createGraphics();
        g2d.fillRect(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        renderer.paint(g2d, imageBounds, bounds);
        g2d.dispose();
        if(destImagePath == null || "".equals(destImagePath)){
            ImageIO.write(dumpImage, "png", response.getOutputStream());
        }else{
            ImageIO.write(dumpImage, "png", new File(destImagePath+".png"));
        }
    }

    public static void main(String[] args) throws  Exception{

        File file = ResourceUtils.getFile("classpath:static/shpTest[Point]/dp_tl.shp");
        // 从shp文件里面读取属性信息
        readShpByPath(file.getAbsolutePath(),10);
        System.out.println("=================下面开始往shp文件里面写几何对象===================");

        // 先创建文件夹test
        String filePath = "C:/test/test.shp";

        String pointWkt="POINT (120.76164848270959 31.22001141278534)";
        Point point = gCreator.createPointByWKT(pointWkt);

        // Polygon【面】
        String polygonWkt="POLYGON ((103.859188 34.695908, 103.85661 34.693788, 103.862027 34.69259, 103.863709 34.695078, 103.859188 34.695908))";
        Polygon polygon = gCreator.createPolygonByWKT(polygonWkt);

        // LineString【线】
        String linestringWkt="LINESTRING(113.511315990174 41.7274734296674,113.51492087909 41.7284983348307,113.516079593384 41.727649586406,113.515907932007 41.7262243043929,113.514019656861 41.7247989907606,113.512131381714 41.7250872589898,113.51138036319 41.7256637915682,113.511315990174 41.7274734296674)";
        LineString lineString = gCreator.createLineByWKT(linestringWkt);

        // MultiPolygon【多面】
        String multiPolyWkt = "MULTIPOLYGON(((101.870371 25.19228,101.873633 25.188183,101.880564 25.184416,101.886808 25.186028,101.892043 25.189969,101.896592 25.190163,101.903716 25.190785,101.905454 25.193464,101.899897 25.196202,101.894146 25.197911,101.891657 25.19826,101.886078 25.197658,101.884211145538 25.2007060137013,101.88172564506 25.1949712942389,101.87874 25.199619,101.874641 25.200998,101.868547 25.202415,101.863741 25.202415,101.85887 25.202842,101.854557 25.202182,101.852604 25.199736,101.852282 25.19628,101.854492 25.194183,101.855608 25.192668,101.863698 25.192105,101.870371 25.19228)))";
        MultiPolygon multiPolygon = gCreator.createMulPolygonByWKT(multiPolyWkt);

        // 几何对象的范围【矩形边界】
        Envelope envelope = polygon.getEnvelopeInternal();
        System.out.println(envelope);

        // 往shp文件里面写几何对象
        writeShpByGeom(filePath,point);
    }

}

七、联系我

CSDN名: Appleyk

CSDN博客:https://blog.csdn.net/Appleyk

本篇CSDN对应博文:https://blog.csdn.net/Appleyk/article/details/83376510

原文地址:https://www.cnblogs.com/appleyk/p/9848787.html

时间: 2024-10-27 01:58:16

Spring-Boot ? ShapeFile文件读写工具类+接口调用的相关文章

spring boot 结合Redis 实现工具类

自己整理了 spring boot 结合 Redis 的工具类引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId></dependency>加入配置 # Redis数据库索引(默认为0)spring.redis.database=0# Redis服务器地址

list集合、txt文件对比的工具类和文件读写工具类

工作上经常会遇到处理大数据的问题,下面两个工具类,是在处理大数据时编写的:推荐的是使用map的方式处理两个list数据,如果遇到list相当大数据这个方法就起到了作用,当时处理了两个十万级的list,使用改方法的变种搞定. 1.txt文件.list集合比较工具 <span style="font-family:KaiTi_GB2312;font-size:18px;">package com.hudong.util.other; import java.util.Colle

Android之文件读写工具类

本工具类永久维护,永久更新,如果各位读者发现有bug或者不合理之处,欢迎指正,博主将第一时间改正. 以下是主要内容,本类主要功能有: 1.创建文件功能: 2.向文件中写入字节数组: 3.向文件中写入字符串: 4.从文件中读取字节数组: 5.从文件中读取字符串: import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; /** * 文件读写工具类 * * @author bear *

Android 文件读写工具类

自己写的工具类,写的不好,慢慢修改. 记得加上权限 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> package com.sy.utils; import android.con

properties文件读写工具类PropertiesUtil.java

import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Properties; /** * * @author * */ public class PropertiesUtil { private String prope

还怕不记得Spring Boot注解吗?5类注解全在这里了(建议收藏)

前言 使用注解的优势:1.采用纯java代码,不在需要配置繁杂的xml文件2.在配置中也可享受面向对象带来的好处3.类型安全对重构可以提供良好的支持4.减少复杂配置文件的同时亦能享受到springIoC容器提供的功能 Spring Boot的核心就是注解.Spring Boot通过各种组合注解,极大地简化了Spring项目的搭建和开发.在Spring Boot中有一些注解是其中的关键,必须掌握.接下来就给大家做详细的介绍. 一.注解(annotations)列表 @SpringBootAppli

spring boot 2 集成JWT实现api接口认证

JSON Web Token(JWT)是目前流行的跨域身份验证解决方案.官网:https://jwt.io/本文spring boot 2 集成JWT实现api接口验证. 一.JWT的数据结构 JWT由header(头信息).payload(有效载荷)和signature(签名)三部分组成的,用“.”连接起来的字符串.JWT的计算逻辑如下:(1)signature = HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(

iOS开发拓展篇—封装音频文件播放工具类

一.简单说明 1.关于音乐播放的简单说明 (1)音乐播放用到一个叫做AVAudioPlayer的类 (2)AVAudioPlayer常用方法 加载音乐文件 - (id)initWithContentsOfURL:(NSURL *)url error:(NSError **)outError; - (id)initWithData:(NSData *)data error:(NSError **)outError; 准备播放(缓冲,提高播放的流畅性) - (BOOL)prepareToPlay;

java文件处理工具类

import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileRea