以下是使用 GeoTools 将 Shapefile 数据导入 PostGIS 的示例代码:
1. 添加依赖
确保你的项目中包含 GeoTools 和 PostGIS 相关的依赖。如果使用 Maven,可以在 pom.xml
中添加以下依赖:
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-shapefile</artifactId>
<version>24.0</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-jdbc-postgis</artifactId>
<version>24.0</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-main</artifactId>
<version>24.0</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.23</version>
</dependency>
2. 代码说明
-
打开 Shapefile 文件:
- 使用
ShapefileDataStore
打开 Shapefile 文件,并获取其FeatureSource
。
- 使用
-
打开 Shapefile的投影文件:
- 指定投影。
-
配置 PostGIS 连接参数:
- 设置 PostGIS 数据库的连接参数,包括用户名、密码、主机、端口、数据库名称等。
-
创建目标表:
- 使用
postgisDataStore.createSchema
方法在 PostGIS 中创建与 Shapefile 结构相同的表。
- 使用
-
批量插入数据:
- 使用
FeatureWriter
和Transaction.AUTO_COMMIT
批量插入数据。FeatureWriter
会逐条写入数据,但通过事务机制可以提高性能。
- 使用
-
关闭资源:
- 操作完成后,关闭 Shapefile 和 PostGIS 的
DataStore
。
- 操作完成后,关闭 Shapefile 和 PostGIS 的
3. 示例代码
以下是将 Shapefile 数据批量导入 PostGIS 的完整代码:
import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFinder;
import org.geotools.data.FeatureWriter;
import org.geotools.data.Transaction;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.jdbc.JDBCDataStore;
import org.geotools.jdbc.JDBCDataStoreFactory;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
public class ShapefileToPostGIS {
public static void main(String[] args) throws IOException {
// 配置 PostGIS 连接参数
Map<String, Serializable> params = new HashMap<>();
params.put(JDBCDataStoreFactory.USER.key, "your_username");
params.put(JDBCDataStoreFactory.PASSWD.key, "your_password");
params.put(JDBCDataStoreFactory.DBTYPE.key, "postgis");
params.put(JDBCDataStoreFactory.HOST.key, "localhost");
params.put(JDBCDataStoreFactory.PORT.key, 5432);
params.put(JDBCDataStoreFactory.DATABASE.key, "your_database");
params.put(JDBCDataStoreFactory.SCHEMA.key, "public"); // 目标 schema
// 目标表名
String tableName = "calc_polygon";
// 打开 SHP 文件
ShapefileDataStore shpDataStore = new ShapefileDataStore(new File("path/to/your/shapefile.shp").toURI().toURL());
shpDataStore.setCharset(Charset.forName("GBK")); // 指定文件编码,避免乱码
SimpleFeatureSource shpFeatureSource = shpDataStore.getFeatureSource();
// 连接到 PostGIS
DataStore postgisDataStore = DataStoreFinder.getDataStore(params);
if(postgisDataStore == null) {
throw new CommonException("PostGIS数据库连接失败");
}
// 检查表是否存在,如果存在则删除, 需自己写sql实现
if (baseMapper.schemaIsExists(tableName)) {
postgisDataStore.removeSchema(tableName);
}
try (FileInputStream fis = new FileInputStream("path/to/your/shapefile.prj")){
// 读取 PRJ 文件设置坐标系
String wktText = new String(fis.readAllBytes());
CoordinateReferenceSystem coordinateReferenceSystem = CRS.parseWKT(wktText);
SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();
typeBuilder.setCRS(coordinateReferenceSystem);
typeBuilder.setName(tableName);
// 添加自定义字段
typeBuilder.add("status", String.class);
typeBuilder.add("现状地物(种植的果树种类等)", String.class);
typeBuilder.add("道路通达条件(机耕道辐射范围150米内)", String.class);
typeBuilder.add("是否有水源(150米内)", String.class);
typeBuilder.add("土壤厚度(cm)", String.class);
// 创建表
postgisDataStore.createSchema(typeBuilder.buildFeatureType());
// 将Shapefile的数据写入PostGIS
try (FeatureWriter<SimpleFeatureType, SimpleFeature> featureWriter = postgisDataStore.getFeatureWriterAppend(tableName, Transaction.AUTO_COMMIT);
SimpleFeatureIterator iterator = shpFeatureSource.getFeatures().features()) {
while (iterator.hasNext()) {
SimpleFeature feature = iterator.next();
SimpleFeature newFeature = featureWriter.next();
// setAttributes可能会报错
// newFeature.setAttributes(feature.getAttributes());
// newFeature.setDefaultGeometry(feature.getDefaultGeometry());
// 建设使用for循环设置属性
for (Property property : feature.getProperties()) {
newFeature.setAttribute(property.getName().toString(), property.getValue());
}
featureWriter.write();
}
return true;
}