前言
项目上有用到Gdal操作gdb数据库文件的操作,网上搜了一圈没有见到有相关工具类,就手写了一个对gdb的相关操作,以作参考
一、引入Gdal
这里我用的是maven直接引入的(本地已经配置gdal环境才行,并且版本对应)
<dependency>
<groupId>org.gdal</groupId>
<artifactId>gdal</artifactId>
<version>3.8.0</version>
</dependency>
如何导入java项目这个网上一搜有很多,跟着做就行啦
二、导入GDB数据
public static final String DEF_GEOM_KEY = "the_geom";
public static final String GEOM_TYPE = "geomType";
static {
gdal.AllRegister();
//注册所有驱动
ogr.RegisterAll();
//支持中文路径
gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
//属性表支持中文
gdal.SetConfigOption("SHAPE_ENCODING", "CP936");
DEF_KET = new SpatialReference(ShpUtil.DEF_KET);
}
/**
* 获取GDB数据
*
* @param path GDB路径
* @param layerName 图层名称
*/
public static List<Map<String, ?>> openGDB(String path, String layerName) {
List<Map<String, ?>> dataList = new ArrayList<>();
// 打开GDB数据源
DataSource dataSource = ogr.Open(path, gdalconst.GA_ReadOnly);
if (dataSource == null) {
System.err.println("无法打开GDB文件");
return null;
}
Layer layer = dataSource.GetLayerByName(layerName);
if (layer == null) {
System.err.println("无法找到名为 " + layerName + " 的图层");
dataSource.delete(); // 关闭数据源
return null;
}
layer.ResetReading(); // 重置读取到图层的开始位置
Feature feature = null;
int i = 0;
while (ObjUtil.isNotEmpty((feature = layer.GetNextFeature()))) {
Map<String, Object> featMap = new HashMap<>();
//获取图斑数据
Geometry geometry = feature.GetGeometryRef();
featMap.put(DEF_GEOM_KEY, geometry.ExportToWkt());
for (i = 0; i < feature.GetFieldCount(); i++) {
int fieldType = feature.GetFieldType(i);
FieldDefn fieldDefn = feature.GetFieldDefnRef(i);
// 根据字段类型进行操作
switch (fieldType) {
case ogrConstants.OFTInteger:
featMap.put(fieldDefn.GetName(), feature.GetFieldAsInteger(i));
break;
case ogrConstants.OFTReal:
featMap.put(fieldDefn.GetName(), feature.GetFieldAsDouble(i));
break;
case ogrConstants.OFTString:
featMap.put(fieldDefn.GetName(), feature.GetFieldAsString(i));
break;
default:
featMap.put(fieldDefn.GetName(), feature.GetFieldAsString(i));
break;
}
}
dataList.add(featMap);
}
layer.delete(); // 释放图层对象
dataSource.delete(); // 关闭数据源
return dataList;
}
三.导出GDB
导入和导出是有点区别的,导出需要FileGDB驱动,下面这行代码检查一下自己是否存在FileGDB驱动
/**
* dev
* 打印驱动列表
*
* @return
*/
public static String printDriverList() {
int count = ogr.GetDriverCount();
String sr = "";
for (int i = 0; i < count; i++) {
String driverName = ogr.GetDriver(i).getName();
sr =sr+","+ driverName;
System.out.print(driverName + "\t");
}
return sr;
}
这里一定要注意,打印要有FileGDB才可以导出
/**
* 导出GDB图层
*
* @param path GDB路径
* @param layerName 图层名称
* @param spatialReference 空间坐标系参考
* @return 是否导出成功
*/
public static Boolean createGDBByLayer(String path, String layerName, SpatialReference spatialReference, List<Map<String, ?>> dataList) {
//获取图层对象
Layer gdbLayer = createLayer(gdb, path, layerName, spatialReference);
builderLayerInfo(gdbLayer, dataList);
return true;
}
public static Boolean builderLayerInfo(Layer gdbLayer, List<Map<String, ?>> dataList) {
builderFeild(gdbLayer, dataList.get(0));
dataList.stream().forEach(item -> {
createFeature(gdbLayer, item);
});
return true;
}
/**
* 构建字段属性
*
* @param layer
* @param stringMap
*/
private static void builderFeild(Layer layer, Map<String, ?> stringMap) {
stringMap.keySet().forEach(key -> {
if (key.equals(GEOM_TYPE) || key.equals(DEF_GEOM_KEY)) {
return;
}
if (ObjUtil.isNotEmpty(ShpUtil.DATA_CLASS_MAP.get(key))) {
FieldDefn oFieldName = new FieldDefn(key.toUpperCase());
//别名
// oFieldName.SetAlternativeName("要素类型");
// 创建字符型属性,字符长度为50
if (ObjUtil.equals(ShpUtil.DATA_CLASS_MAP.get(key), "String")) {
oFieldName.SetType(ogr.OFTString);
}
if (ObjUtil.equals(ShpUtil.DATA_CLASS_MAP.get(key), "Double")) {
oFieldName.SetType(ogr.OFTReal);
}
if (ObjUtil.equals(ShpUtil.DATA_CLASS_MAP.get(key), "Integer")) {
oFieldName.SetType(ogr.OFTInteger);
}
layer.CreateField(oFieldName);
}
});
}
/**
* 传入Geometry创建一条Feature
*
* @param layer
* @param stringMap
*/
public static void createFeature(Layer layer, Map<String, ?> stringMap) {
FeatureDefn featureDefn = layer.GetLayerDefn();
Feature feature = new Feature(featureDefn);
stringMap.keySet().forEach(key -> {
//地理位置信息
if (key.equals(DEF_GEOM_KEY)) {
Geometry geometry = ogr.CreateGeometryFromWkt((String) stringMap.get(key));
feature.SetGeometry(geometry);
return;
}
if (ObjUtil.isNotEmpty(stringMap.get(key)) && ObjUtil.isNotEmpty(ShpUtil.DATA_CLASS_MAP.get(key))) {
//其他数据
feature.SetField(key.toUpperCase(), String.valueOf(stringMap.get(key)));
}
});
layer.CreateFeature(feature);
}
/**
* 创建矢量图层
*
* @param driverName:驱动名称
* @param path:图层保存路径,要和驱动匹配
* @param layerName:图层名称
* @param spatialReference:图层空间参考
* @return 返回创建好的图层
*/
public static Layer createLayer(String driverName, String path, String layerName, SpatialReference spatialReference) {
Layer result = null;
Driver driver = ogr.GetDriverByName(driverName);
if (driver == null) {
log.info(driverName + "不可用");
System.out.println(driverName + "不可用");
return null;
}
DataSource dataSource = null;
File file = new File(path);
dataSource = driver.CreateDataSource(path, null);
//类型为多边形
result = dataSource.CreateLayer(layerName, spatialReference, ogr.wkbMultiPolygon, null);
return result;
}
结语
目前就是这些,上面代码可能有部分地方需要结合自己的业务来改一下,
结束!有什么问题和建议也欢迎来打扰哦!Q-Q