You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用GeoTools API创建并填充shp文件

没问题!在Java里创建并填充Shapefile,GeoTools库是业内最常用的工具——它提供了一套完整的API来处理GIS数据的创建、读写操作。下面我给你一个完整的示例,从搭建依赖到实现核心逻辑的全流程:

1. 添加GeoTools依赖(Maven为例)

GeoTools的包不在默认Maven中央仓库,所以得先配置仓库,再引入核心依赖:

<repositories>
    <repository>
        <id>osgeo</id>
        <name>OSGeo Release Repository</name>
        <url>https://repo.osgeo.org/repository/release/</url>
        <snapshots><enabled>false</enabled></snapshots>
        <releases><enabled>true</enabled></releases>
    </repository>
</repositories>

<dependencies>
    <!-- GeoTools核心依赖 -->
    <dependency>
        <groupId>org.geotools</groupId>
        <artifactId>gt-shapefile</artifactId>
        <version>28.2</version> <!-- 可以替换为最新稳定版 -->
    </dependency>
    <dependency>
        <groupId>org.geotools</groupId>
        <artifactId>gt-data</artifactId>
        <version>28.2</version>
    </dependency>
    <dependency>
        <groupId>org.geotools</groupId>
        <artifactId>gt-epsg-wkt</artifactId>
        <version>28.2</version>
    </dependency>
</dependencies>
2. 定义业务数据实体类

假设你的Java集合里存的是带坐标的点位数据,先定义一个实体类来封装这些信息:

public class PointData {
    private String name; // 自定义属性:点位名称
    private double lat; // 纬度
    private double lon; // 经度
    private int value; // 自定义属性:关联数值

    // 构造器、getter方法
    public PointData(String name, double lat, double lon, int value) {
        this.name = name;
        this.lat = lat;
        this.lon = lon;
        this.value = value;
    }

    public String getName() { return name; }
    public double getLat() { return lat; }
    public double getLon() { return lon; }
    public int getValue() { return value; }
}
3. 核心实现:创建并填充Shapefile

下面是核心代码,包含创建空Shapefile、定义要素结构、遍历集合写入数据的完整逻辑:

import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFinder;
import org.geotools.data.DefaultTransaction;
import org.geotools.data.Transaction;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.data.simple.SimpleFeatureStore;
import org.geotools.feature.DefaultFeatureCollection;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ShapefileCreator {

    public static void createAndFillShapefile(List<PointData> dataList, String outputPath) throws Exception {
        // 1. 定义Shapefile的要素类型(结构:自定义属性+几何图形)
        SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();
        typeBuilder.setName("PointLayer");
        typeBuilder.setCRS(DefaultGeographicCRS.WGS84); // 设置坐标系为WGS84(经纬度)

        // 添加自定义属性
        typeBuilder.add("name", String.class);
        typeBuilder.add("value", Integer.class);
        // 添加几何属性(Point类型,对应点位数据)
        typeBuilder.add("the_geom", Point.class);

        SimpleFeatureType featureType = typeBuilder.buildFeatureType();

        // 2. 创建Shapefile数据存储
        File shapefile = new File(outputPath);
        Map<String, Object> params = new HashMap<>();
        params.put("url", shapefile.toURI().toURL());
        params.put("create spatial index", Boolean.TRUE);

        DataStore dataStore = DataStoreFinder.getDataStore(params);
        if (dataStore instanceof ShapefileDataStore) {
            ((ShapefileDataStore) dataStore).setCharset(StandardCharsets.UTF_8); // 设置UTF-8避免中文乱码
        }
        dataStore.createSchema(featureType);

        // 3. 将Java集合数据转换为GIS要素
        DefaultFeatureCollection featureCollection = new DefaultFeatureCollection("internal", featureType);
        GeometryFactory geometryFactory = new GeometryFactory();
        SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(featureType);

        for (PointData data : dataList) {
            // 创建JTS Point对象:注意顺序是「经度, 纬度」
            Coordinate coordinate = new Coordinate(data.getLon(), data.getLat());
            Point point = geometryFactory.createPoint(coordinate);

            // 填充要素属性
            featureBuilder.set("name", data.getName());
            featureBuilder.set("value", data.getValue());
            featureBuilder.set("the_geom", point);

            // 构建要素(ID用索引生成,也可以自定义唯一标识)
            SimpleFeature feature = featureBuilder.buildFeature(String.valueOf(dataList.indexOf(data)));
            featureCollection.add(feature);
        }

        // 4. 将要素写入Shapefile
        Transaction transaction = new DefaultTransaction("create");
        String typeName = dataStore.getTypeNames()[0];
        SimpleFeatureSource featureSource = dataStore.getFeatureSource(typeName);

        if (featureSource instanceof SimpleFeatureStore) {
            SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;
            featureStore.setTransaction(transaction);
            try {
                featureStore.addFeatures(featureCollection);
                transaction.commit();
                System.out.println("Shapefile创建并填充成功!路径:" + outputPath);
            } catch (Exception e) {
                transaction.rollback();
                throw new RuntimeException("写入数据失败", e);
            } finally {
                transaction.close();
                dataStore.dispose(); // 释放资源,避免内存泄漏
            }
        }
    }

    // 测试方法:模拟业务数据并执行创建
    public static void main(String[] args) throws Exception {
        // 模拟你的Java集合数据
        List<PointData> dataList = List.of(
                new PointData("北京", 39.9042, 116.4074, 100),
                new PointData("上海", 31.2304, 121.4737, 200),
                new PointData("广州", 23.1291, 113.2644, 300)
        );

        // 输出路径:当前目录下的test.shp
        String outputPath = "./test.shp";
        createAndFillShapefile(dataList, outputPath);
    }
}
关键注意点
  • 坐标系: 示例用了WGS84(EPSG:4326),如果你的数据是投影坐标系(比如墨卡托),需要替换对应的CRS参数。
  • 几何顺序: JTS库创建Point时,必须是「经度在前,纬度在后」,别搞反了!
  • 编码设置: 一定要设置UTF-8编码,否则属性中的中文会出现乱码。
  • 资源释放: 操作完成后要关闭TransactionDataStore,避免资源泄漏。

内容的提问来源于stack exchange,提问作者J. L. Pacheco

火山引擎 最新活动