说点废话:越来越觉得自己渺小,以前只在前端用些turf做过简单的空间分析了解ogc,后来慢慢接触到geotools,再后来发现geotools也有不顶用的时候,直到又发现了gdal,感觉打开了新世界的大门。
配置GDAL调用环境
GDAL开源读取arcgis数据(shape,ged,mdb等)的方案,由C++编写,Java可以调用
1.下载GDAL
//下载地址,不会*的话下载很慢
https://www.gisinternals.com/
//懒得下可以用我下好的
链接: https://pan.baidu.com/s/1sjLHrxBKpubO6Uwfvkj6qw 提取码: uijm 复制这段内容后打开百度网盘手机App,操作更方便哦
2.下载下来获取到文件并解压,并配置java调用环境变量
让java能调用dll文件
将解压目录下bin目录下的dll文件全部复制到java安装路径的bin目录下:C:\Program Files\Java\jdk1.8.0_171\bin
并将bin/gdal/java下的dll调用文件同样复制到jdk环境下C:\Program Files\Java\jdk1.8.0_171\bin
配置环境变量
3.maven配置调用的jar
新建lib目录并将\bin\gdal\java\gdal.jar放到里面
配置jar地址
<dependency>
<groupId>org.gdal</groupId>
<artifactId>gdal</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/gdal.jar</systemPath>
</dependency>
spring boot配置引入外部jar包打包(请注意我这里的spring boot是打包成war)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webResources>
<resource>
<directory>lib</directory>
<targetPath>WEB-INF/lib/</targetPath>
<includes>
<include>**/gdal.jar</include>
</includes>
</resource>
</webResources>
</configuration>
</plugin>
至此我们的环境设置已经完成了。
java 调用gdal
package com.ruoyi;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.ReUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.ruoyi.common.utils.JdbcUtils;
import com.ruoyi.common.utils.UnitConverionUtils;
import com.ruoyi.project.zrzy.domain.CityCode;
import com.ruoyi.project.zrzy.service.IVitUplodFileService;
import org.gdal.gdal.gdal;
import org.gdal.ogr.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @Auther: jhwang
* @Date: 2021/4/27 09:23
* @Description:
*/
@RunWith(SpringRunner.class) //这两个注解是为了让测试类能拥有同等的spring boot上下文环境
@SpringBootTest
public class GDBread2 {
static {
gdal.AllRegister();//设置gdal环境
}
// /**
// * 从GDB中读取行政区划数据并返回
// * 读不出来,连表查询有问题
// * @return
// */
// public void selectGDBCity(String year){
// JdbcTemplate xzqh = JdbcUtils.getJdbcTemplate("xzqh");
// List<CityCode> query = xzqh.query(getCitySql(year),
// (rs, rowNum) -> {
// CityCode cityCode = new CityCode();
// cityCode.setPac(rs.getString("pac"));
// return cityCode;
// }
// );
// Console.log();
// File[] ls = FileUtil.ls(cityFileFolder);
// Map map = new HashMap<>();
// Driver driver = ogr.GetDriverByName("OpenFileGDB"); //设置驱动
// for (int i = 0; i < ls.length; i++) {
// String filePath = ls[i].getPath();
// String year = ReUtil.get("\\d+", ls[i].getName(), 0);
// List<CityCode> list = new ArrayList<>();
// DataSource dataSource = driver.Open(filePath, 0);
// Layer querylayer = dataSource.ExecuteSQL("select DISTINCT f.pac as pac ,f.SHAPE_Area as area ,m.name as name ,m.gb as gb,m.level from (select t.pac,sum(t.SHAPE_Area) as SHAPE_Area from (select name,gb,pac,SHAPE_Area from v_boua2 UNION select name,gb,pac,SHAPE_Area from v_boua4 UNION select name,gb,pac,SHAPE_Area from v_boua5 UNION select name,gb,pac,SHAPE_Area from v_boua6 order by gb) t group by t.pac) f left join (select name,gb,pac,SHAPE_Area,'0' as level from v_boua2 UNION select name,gb,pac,SHAPE_Area,'1' as level from v_boua4 UNION select name,gb,pac,SHAPE_Area,'2' as level from v_boua5 UNION select name,gb,pac,SHAPE_Area,'3' as level from v_boua6 ) m on m.pac = f.pac order by f.pac");
//
// //测试是否支持统计查询(测试完全支持统计查询)
// //Layer querylayer = dataSource.ExecuteSQL("select sum(SHAPE_Area) as s from v_boua5");
// //好像是不支持关联查询,有点狗了
//
// do {//获取图层下的要素
// Feature feature = querylayer.GetNextFeature();
// if (null == feature) {break;}
// CityCode cityCode = new CityCode();
// cityCode.setPac(feature.GetFieldAsString("pac"));
// cityCode.setArea(new BigDecimal(feature.GetFieldAsString("SHAPE_Area")));
// cityCode.setGb(feature.GetFieldAsString("gb"));
// cityCode.setName(feature.GetFieldAsString("name"));
// list.add(cityCode);
// } while (true);
// map.put(year,list);
// }
// Console.log(map);
// }
private static Object getProperty(Feature feature, int index) {
int type = feature.GetFieldType(index);
GDBread2.PropertyGetter propertyGetter;
if (type < 0 || type >= propertyGetters.length) {
propertyGetter = stringPropertyGetter;
} else {
propertyGetter = propertyGetters[type];
}
try {
return propertyGetter.get(feature, index);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 属性获取器
*/
@FunctionalInterface
private interface PropertyGetter {
Object get(Feature feature, int index);
}
private static final GDBread2.PropertyGetter stringPropertyGetter = (feature, index) -> feature.GetFieldAsString(index);
/**
* feature.GetFieldType(index)得到一个属性类型的int值,该值对应具体类型
*/
private static final GDBread2.PropertyGetter[] propertyGetters = new GDBread2.PropertyGetter[]{
(feature, index) -> feature.GetFieldAsInteger(index),//0 Integer
(feature, index) -> feature.GetFieldAsIntegerList(index),//1 IntegerList
(feature, index) -> feature.GetFieldAsDouble(index),//2 Real
(feature, index) -> feature.GetFieldAsDoubleList(index),//3 RealList
stringPropertyGetter,//4 String
(feature, index) -> feature.GetFieldAsStringList(index),//5 StringList
stringPropertyGetter,//6 (unknown)
stringPropertyGetter,//7 (unknown)
(feature, index) -> feature.GetFieldAsBinary(index),//8 Binary
(feature, index) -> {
int[] pnYear = new int[1];
int[] pnMonth = new int[1];
int[] pnDay = new int[1];
int[] pnHour = new int[1];
int[] pnMinute = new int[1];
float[] pfSecond = new float[1];
int[] pnTZFlag = new int[1];
feature.GetFieldAsDateTime(index, pnYear, pnMonth, pnDay, pnHour, pnMinute, pfSecond, pnTZFlag);
java.sql.Date date = java.sql.Date.valueOf(LocalDate.of(pnYear[0], pnMonth[0], pnDay[0]));
return date;
},//9 Date
(feature, index) -> {
int[] pnYear = new int[1];
int[] pnMonth = new int[1];
int[] pnDay = new int[1];
int[] pnHour = new int[1];
int[] pnMinute = new int[1];
float[] pfSecond = new float[1];
int[] pnTZFlag = new int[1];
feature.GetFieldAsDateTime(index, pnYear, pnMonth, pnDay, pnHour, pnMinute, pfSecond, pnTZFlag);
float fSecond = pfSecond[0];
int s = (int) fSecond;
int ns = (int) (1000000000 * fSecond - s);
Time time = Time.valueOf(LocalTime.of(pnHour[0], pnMinute[0], s, ns));
return time;
},// 10 Time
(feature, index) -> {
int[] pnYear = new int[1];
int[] pnMonth = new int[1];
int[] pnDay = new int[1];
int[] pnHour = new int[1];
int[] pnMinute = new int[1];
float[] pfSecond = new float[1];
int[] pnTZFlag = new int[1];
feature.GetFieldAsDateTime(index, pnYear, pnMonth, pnDay, pnHour, pnMinute, pfSecond, pnTZFlag);
float fSecond = pfSecond[0];
int s = (int) fSecond;
int ns = (int) (1000000000 * fSecond - s);
LocalDateTime localDateTime = LocalDateTime.of(
LocalDate.of(pnYear[0], pnMonth[0], pnDay[0]),
LocalTime.of(pnHour[0], pnMinute[0], s, ns)
);
Timestamp timestamp = Timestamp.valueOf(localDateTime);
return timestamp;
},//11 DateTime
(feature, index) -> feature.GetFieldAsInteger64(index),//12 Integer64
(feature, index) -> feature.GetFieldAsIntegerList(index),//13 Integer64List
//>=14 (unknown)
};
/**
* 不存在则级联创建文件
* @param path
*/
private static void CreateFile(String path){
File testFile = new File(path);
String parent = testFile.getParent();
if(!new File(parent).exists()){
new File(parent).mkdirs();
}
if (!testFile.exists()) {
try {
testFile.createNewFile();// 能创建多级目录
} catch (IOException e) {
e.printStackTrace();
}
}
}
}