java 使用 geotools 将 shp 文件(zip压缩包)转换为 geoJson 格式

步骤0:你也可以参考这篇文章 :java实现geojson格式数据与shp文件相互转换

步骤1:引入引入geotools工具。

步骤2:编写工具类,获取shp的zip文件。

步骤3:编写工具类,解析shp文件成为jsonObject (geoJson)。

步骤4:拿到你的jsonObject,供你使用。


步骤1:引入geotools工具,笔者全网找半天也没在中文局域网里找到引入的方法,而是在公司同事的pom文件找到了:

<!--    shp文件解析 开始    -->
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-shapefile</artifactId>
            <version>19.2</version>
        </dependency>
        <dependency>
            <groupId>org.ejml</groupId>
            <artifactId>ejml-ddense</artifactId>
            <version>0.39</version>
        </dependency>
        <dependency>
            <groupId>org.ejml</groupId>
            <artifactId>ejml-core</artifactId>
            <version>0.39</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-opengis</artifactId>
            <version>19.2</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-data</artifactId>
            <version>19.2</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-api</artifactId>
            <version>19.2</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-main</artifactId>
            <version>19.2</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-metadata</artifactId>
            <version>19.2</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-referencing</artifactId>
            <version>19.2</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-geojson</artifactId>
            <version>19.2</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.5</version>
        </dependency>
        <dependency>
            <groupId>javax.measure</groupId>
            <artifactId>jsr-275-1.0-beta</artifactId>
            <version>2</version>
        </dependency>
        <dependency>
            <groupId>com.vividsolutions</groupId>
            <artifactId>jts</artifactId>
            <version>1.13</version>
        </dependency>
       
        <!--    shp文件解析 结束    -->

你也可以参考来引入geotools:Maven中GeoTools的引入 - Maven 的 repository 与 mirror


步骤2:编写工具类,编写获取shp的zip文件的方法getFeatureCollectionByShpFile()。(该方法是为了将shp的zip压缩包解析后拿到FeatureCollection集合,其中需要自定义的 ZipUtil 解压到随机文件夹)

ShapeFileUtil工具类:

public class ShapeFileUtil {
    /*
     * @param zipFile: 压缩包文件地址
      * @return FeatureCollection
     * @author pangshicheng
     * @description 解析shp压缩包,并返回解析出的 FeatureCollection
     * @date 2023/7/18 16:02
     */
    public static FeatureCollection getFeatureCollectionByShpFile(File zipFile) throws IOException {
        try {
            String tempDir = FileUtil.getTempDirPath();
            File shapeDir = new File(tempDir + File.separator + new Date().getTime());
            shapeDir.mkdir();
            List<String> files = ZipUtil.unZipFiles(zipFile, shapeDir.getPath() + File.separator);
            String shapFileName = "";
            for (String fileName : files) {
                String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
                if ("shp".equals(suffix)) {
                    shapFileName = fileName;
                }
            }
            File shapeFile = new File(shapFileName);
            List<SimpleFeature> list = new ArrayList<>();
            Map<String, Object> shapeFileParams = new HashMap();
            shapeFileParams.put("url", shapeFile.toURI().toURL());
            // 设置编码
            shapeFileParams.put("charset", "GBK");
            DataStore dataStore = DataStoreFinder.getDataStore(shapeFileParams);
            if (dataStore == null) {
                throw new RuntimeException("couldn't load the damn data store: " + shapeFileParams);
            }
            String typeName = dataStore.getTypeNames()[0];
            FeatureSource<SimpleFeatureType, SimpleFeature> source = dataStore.getFeatureSource(typeName);
            Filter filter = Filter.INCLUDE;
            FeatureCollection<SimpleFeatureType, SimpleFeature> collection = source.getFeatures(filter);
            return collection;
        }catch (Exception e){
            throw e;
        }
    }
}

ZipUtil工具类:

/**
 * @author soulmate丶
 * @date 2021-10-26
 */
public class ZipUtil {

    private static final Logger log = LoggerFactory.getLogger(ZipUtil.class);
    /**
     * 保存zip文件到本地并调用解压方法并返回解压出的文件的路径集合
     *
     * @param file 文件
     * @return list //解压出的文件的路径合集
     */
    private static String zipPath = "f:/shpfile/";//zip根路径

    /**
     * zip解压
     *
     * @param srcFile     zip源文件
     * @param destDirPath 解压后的目标文件夹
     * @return list 解压文件的路径合集
     * @throws RuntimeException 解压失败会抛出运行时异常
     */
    public static List<String> unZipFiles(File srcFile, String destDirPath) throws RuntimeException {
        List<String> list = new ArrayList<>();
        long start = System.currentTimeMillis();
        // 判断源文件是否存在
        if (!srcFile.exists()) {
            throw new RuntimeException(srcFile.getPath() + "所指文件不存在");
        }
        // 开始解压
        ZipFile zipFile = null;
        try {
            zipFile = new ZipFile(srcFile, Charset.forName("GBK"));
            Enumeration<?> entries = zipFile.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = (ZipEntry) entries.nextElement();
                log.info("解压" + entry.getName());
                // 如果是文件夹,就创建个文件夹
                if (entry.isDirectory()) {
                    String dirPath = destDirPath + File.separator + entry.getName();
                    File dir = new File(dirPath);
                    dir.mkdirs();
                } else {
                    // 如果是文件,就先创建一个文件,然后用io流把内容copy过去
                    File targetFile = new File(destDirPath + File.separator + entry.getName());
                    // 保证这个文件的父文件夹必须要存在
                    log.info(destDirPath + entry.getName());
                    list.add(destDirPath + entry.getName());
                    if (!targetFile.getParentFile().exists()) {
                        log.info("父文件不存在");
                    }
                    targetFile.createNewFile();
                    // 将压缩文件内容写入到这个文件中
                    InputStream is = zipFile.getInputStream(entry);
                    FileOutputStream fos = new FileOutputStream(targetFile);
                    int len;
                    byte[] buf = new byte[1024];
                    while ((len = is.read(buf)) != -1) {
                        fos.write(buf, 0, len);
                    }
                    // 关流顺序,先打开的后关闭
                    fos.close();
                    is.close();
                }
            }
            long end = System.currentTimeMillis();
            log.info("解压完成,耗时:" + (end - start) + " ms");
        } catch (Exception e) {
            throw new RuntimeException("unzip error from ZipUtils", e);
        } finally {
            if (zipFile != null) {
                try {
                    zipFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return list;
    }

    /**
     * @param filePath 临时文件的删除
     *                 删除文件夹里面子目录
     *                 再删除文件夹
     */
    public static void deleteFiles(String filePath) {
        File file = new File(filePath);
        if ((!file.exists()) || (!file.isDirectory())) {
            log.info("file not exist");
            return;
        }
        String[] tempList = file.list();
        File temp = null;
        for (int i = 0; i < tempList.length; i++) {
            if (filePath.endsWith(File.separator)) {
                temp = new File(filePath + tempList[i]);
            } else {
                temp = new File(filePath + File.separator + tempList[i]);
            }
            if (temp.isFile()) {
                temp.delete();
            }
            if (temp.isDirectory()) {
                deleteFiles(filePath + "\\" + tempList[i]);
            }
        }
        // 空文件的删除
        file.delete();
    }
}


步骤3:在相同工具类编写方法shpToGeoJson(),解析shp文件成为jsonObject (geoJson)。

/**
     * @param zipFile:
      * @return JSONObject
     * @author pangshicheng
     * @description 通过shp压缩文件,将其转换为GeoJson格式
     * @date 2023/7/18 16:04
     */
    public static JSONObject shpToGeoJson(File zipFile) throws IOException {
        FeatureJSON fjson = new FeatureJSON();
        JSONObject geoJsonObject=new JSONObject();
        geoJsonObject.put("type","FeatureCollection");
        try {
            // 获取FeatureCollection
            FeatureCollection collection = getFeatureCollectionByShpFile(zipFile);

            FeatureIterator iterator = collection.features();
            List<JSONObject> array  = new ArrayList<JSONObject>();
            //遍历feature转为json对象
            while (iterator.hasNext()) {
                SimpleFeature feature = (SimpleFeature) iterator.next();
                StringWriter writer = new StringWriter();
                fjson.writeFeature(feature, writer);
                String temp = writer.toString();
                byte[] b = temp.getBytes("iso8859-1");
                temp = new String(b, "gbk");
                JSONObject json = JSONObject.parseObject(temp);
                array.add(json);
            }
            iterator.close();
            //添加到geojsonObject
            geoJsonObject.put("features",array);
            iterator.close();

        }catch (Exception e){
            throw e;
        }
        return geoJsonObject;
    }

步骤4:拿到你的jsonObject,供你使用。
在这里插入图片描述
在这里插入图片描述

方式二:在前端使用shapefile插件来直接转换

<el-upload
                                    v-model:file-list="uploadShpList"
                                    :http-request="uploadSectionFile"
                                    action="#"
                                    multiple
                                    :limit="1"
                                    :data="{
                                    bucketName: 'map',
                                    acceptFile: 'rar'
                                }"
                                    :on-success="uploadSuccess"
                            >
                                <el-button type="primary">上传矢量数据</el-button>
                            </el-upload>
function uploadSuccess(response, uploadFile, uploadFiles) {
        console.log(response)
        console.log(uploadFile)
    }

    function uploadSectionFile(params) {
        const file = params.file
        const fileName = file.name
        const isZip = fileName.indexOf('zip') !== -1
        const isShp = fileName.indexOf('shp') !== -1

        if (!(isZip || isShp)) {
            return false
        } else {
            loading.value = true;
            isZip ? openZip(file) : toGeo(file)
        }
    }

    // 为zip时,读取压缩包,选取shp文件
    function openZip(data) {
        var newZip = new JsZip()
        newZip.loadAsync(data).then(function (file) {
            // 压缩包里的内容file.files
            const fileList = Object.keys(file.files)
            const pattern = new RegExp(/\S\.shp$/)
            let shpFile = fileList.find(i => pattern.test(i))
            newZip.file(shpFile).async('arraybuffer') // 此处是压缩包中的shp文件,arraybuffer(此时在回调的参数中已经可以获取到上传的zip压缩包下的所有文件)
                .then(function (content) { // 这个就是文件中的内容
                    shapeFileOpen(content)
                })
        }).catch(err => {
            // 是否是合法的zip包,解决rar包改后缀zip
            console.log(err)
        })
    }

    // 转ArrayBuffer
    function toGeo(data) {
        const reader = new FileReader()
        reader.readAsArrayBuffer(data)
        reader.onload = function (e) {
            shapeFileOpen(this.result)
        }
    }

    // shapefile插件 shp转geo
    function shapeFileOpen(content) {
        let features = []
        open(content).then(source => source.read().then(function log(result) {

                if (result.done) {
                    if (features.length > 1) {
                        //这部分纯粹为了把很多平面拼在一起,你也可以根据自己的需求拼接
                        const cList = features.map(ele => {
                            return ele.geometry.coordinates
                        })
                        const geojson = {
                            type: 'Feature',
                            properties: {},
                            geometry: {
                                type: 'MultiPolygon',
                                coordinates: cList
                            }
                        }
                        //上传接口
                    } else {
                        //上传接口
                    }
                    return
                }
                features.push(result.value) //多个面时,会打印每一个,这样就先把他们放在一个集合里
                return source.read().then(log)
            })
        ).catch(error => console.error(error.stack)).finally(()=>{
            let geoJson ={
                type: "FeatureCollection",
                name: "100000_full",
                features: features

            }
        })
    }

拿到的 geoJson 就是我们要的结果。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值