Linux(centos8)GDAL 2.2.1 升级为 GDAL 3.3.2
一、背景:
之前篇“ Linux(centos8)安装 GDAL 2.2.1”见:
Linux(centos8)系统安装编译GDAL 2.2.1 - 简书 (jianshu.com)
由于 GDAL 2.2.1
有在 dxf
转 geojson
过程中存在问题:
- 问题1:
多行文本类型,解析出来会出现特殊符号(各种cad中非标准的转义字符,比如C5...); - 问题2:
已知线型转换坐标错误:
"SubClasses": "AcDbEntity:AcDbSpline",
"EntityHandle": "8172",
"Linetype": "ACAD_ISO03W100",
"Layer": "18-1.推测冲刷构造"
已经在
windows
上的3.3.1
版本验证过,不存在这类问题,所以现在要把linux
上的gdal
版本升级到最新的3.3.2
。
二、环境介绍:
linux系统:
[root@cumt gdal-2.2.1]# cat /proc/version
Linux version 4.18.0-193.el8.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 8.3.1 20191121 (Red Hat 8.3.1-5) (GCC)) #1 SMP Fri May 8 10:59:10 UTC 2020
三、安装步骤:
- 下载
gdal-3.3.2
:
# wget -c -P /storage/software/gdal http://download.osgeo.org/gdal/3.3.2/gdal-3.3.2.tar.gz
- 解压并进入
gdal-3.3.2
目录:
# tar xvf gdal-3.3.2.tar.gz
# cd /storage/software/gdal-3.3.2
- 执行配置:
# ./configure
# make
# make install
- 报错1:缺少
PROJ
,需要安装
configure: error: PROJ 6 symbols not found
见:linux 安装 PROJ - 简书 (jianshu.com)
- 安装升级成功之后,查看版本:
# gdalinfo --version
四、java集成gdal:
一、介绍:
我是java
程序里调用了本地的gdal
,所以按照官方要求:
- 编译
gdal 3.3.2
自带的java
的jar
包依赖,然后我选择把它打到我的maven
仓库中去再引入。 - 需要配置一些动态链接库
相关的java
代码:
package com.hongyi.cms.gismap.util;
/**
* java 集成 gdal,参考:https://blog.csdn.net/liqian_ken/article/details/109228081?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-9.base&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-9.base
* ## 下载:https://www.gisinternals.com/query.html?content=filelist&file=release-1916-x64-gdal-3-3-1-mapserver-7-6-4.zip
* 其中的:release-1916-x64-gdal-3-3-1-mapserver-7-6-4.zip 2021-07-31 21:57:57 51942 kB Compiled binaries in a single .zip package
* ## java项目引入gdal依赖:
* 1.把bin下所有dll文件复制到jdk/bin下,
* 2.把bin/gdal/java/下的dll复制到jdk/bin下,
* 3.把bin/gdal/java/下的gdal.jar添加到java项目的lib中(外引:F:\ckk\software\release-1916-x64-gdal-3-3-1-mapserver-7-6-4\bin\gdal\java\gdal.jar)。
*/
import com.hongyi.cms.gismap.util.file.operate.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.gdal.gdal.gdal;
import org.gdal.ogr.*;
import org.gdal.osr.SpatialReference;
/**
* dxf 转 geojson
*/
@Slf4j
public class Cad2GeoJsonUtil {
/**
* dxf转geojson(矢量拆分)
* @param inputPath
* @param cadFileName
* @param outputPath
* @return
*/
public static boolean dxf2GeoJson(String inputPath, String cadFileName, String outputPath){
try {
ogr.RegisterAll();
// gdal.SetConfigOption 选项配置参见:https://trac.osgeo.org/gdal/wiki/ConfigOptions
// 为了支持中文路径,请添加下面这句代码
gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
// 为了使属性表字段支持中文,请添加下面这句
gdal.SetConfigOption("SHAPE_ENCODING", "");
//设置DXF缺省编码
gdal.SetConfigOption("DXF_ENCODING", "ASCII");
// String inputPath = "F:\\ckk\\mapbox研究\\java集成gdal\\xjlmk.dxf";
DataSource ds = ogr.Open(inputPath + cadFileName, 0);
if (ds == null) {
log.info("打开dxf文件失败!filePath="+inputPath + cadFileName);
return false;
}
log.info("打开dxf文件成功!");
// 拆分矢量文件为多个单要素矢量文件,注意拆分后的fid需要重置,
String fieldName = null;
// String saveFolderPath = "F:\\ckk\\mapbox研究\\java集成gdal\\xjlmk-1628561264202\\";// 生成的矢量文件保存目录
String saveFolderPath = outputPath;// 生成的矢量文件保存目录
boolean dirExists = FileUtil.judgeDirExists(saveFolderPath, true);
if(!dirExists){
log.error("dxf2GeoJson,文件目录创建失败!saveFolderPath ="+saveFolderPath);
return false;
}
Driver dv = ogr.GetDriverByName("GeoJSON");
if (dv == null) {
log.error("打开GeoJSON驱动失败!");
return false;
}
log.info("打开GeoJSON驱动成功!");
Layer layer = ds.GetLayer(0);
SpatialReference spatial = layer.GetSpatialRef();
int geomType = layer.GetGeomType();
FeatureDefn layerDefn = layer.GetLayerDefn();
int fieldCount = layerDefn.GetFieldCount();
Feature feature = layer.GetNextFeature();
int count = 1;
while(feature != null){
// Feature featureCopy = feature.Clone();
String outName = "", outLayerName = "";
if(fieldName == null){
Long fid = feature.GetFID();
// int fid = feature.GetFID();
outName = String.valueOf(fid);
outLayerName = String.valueOf(fid);
}else{
outLayerName = feature.GetFieldAsString(fieldName);
outName = outLayerName;
}
if(outName == null){
continue;
}
String outFileName = outName + ".geojson";
int dir = count % 100;// 需要分页储存,因为geojson文件过多,严重影响写入和读取效率。
String subDir = saveFolderPath + dir + "/";
if(!FileUtil.judgeDirExists(subDir, true)){
log.error("dxf2GeoJson,文件子目录创建失败!subDir ="+subDir);
return false;
}
String outFilePath = subDir + outFileName;
DataSource outData = dv.CreateDataSource(outFilePath);
Layer outLayer = outData.CreateLayer(outLayerName, spatial, geomType);
for(int i=0; i<fieldCount; i++){
FieldDefn fieldDefn = layerDefn.GetFieldDefn(i);
outLayer.CreateField(fieldDefn);
}
// outLayer = outData.GetLayer();
feature.SetFID(0l);
outLayer.CreateFeature(feature);
feature = layer.GetNextFeature();
// 此处不执行delete()的话,会导致json文件生成缺少结尾
if (outLayer != null) {
outLayer.delete();
}
if (outData != null) {
outData.delete();
}
count++;
}
// 可选
// gdal.GDALDestroyDriverManager();// 此处会导致 java bug
System.out.println("dxf2GeoJson完毕!!");
return true;
}catch (Exception e){
e.printStackTrace();
log.error("异常:方法dxf2GeoJson!");
return false;
}finally {
// if (ds != null) { // 此处会导致 java bug
// ds.delete();
// }
// if (outLayer != null) {
// outLayer.delete();
// }
// if (outData != null) {
// outData.delete();
// }
}
}
public static void main(String[] args) {
// 注意:本地运行,需要修改pom文件中引入的gdal依赖,修改成windows用的那一版,临时注释掉linux用的那版依赖
// 1.dxf 转 geojson
boolean b = dxf2GeoJson("F:\\ckk\\mapbox研究\\java集成gdal\\", "葫芦素-最新.dxf", "E:\\storage\\spring" +
"-cloud-service" +
"\\gismap1\\784085395322318864\\test\\");
System.out.println("bbbbbb==="+b);
}
}
插一句,关于jdk
的问题:
首先,因为我的jdk
一直用的 openjdk version "1.8.0_302"
,版本老,在gdal
运行时候会报错:
Caused by: javax.net.ssl.SSLHandshakeException: The server selected protocol version TLS10 is not accepted by client preferences [TLS12]
说是jdk
版本的问题,需要注释掉 java.security
中的一些代码,这个我这边试了没行得通,现有的服务器上也正在跑着应用,所以没有进行jdk
的更换。而是指定高版本的jdk
即可。
部署应用到linux上,/opt/jdk1.8.221/bin/java -jar AppGismap.jar
运行后,ogr.RegisterAll();
这行报错:
Native library load failed.
java.lang.UnsatisfiedLinkError: no gdalalljni in java.library.path
“本地gdal依赖库加载失败!在java库路径中没有找到gdalalljni!!”
问题分析:
之前在windows
上用java集成gdal
是把一些dll动态链接库
复制到jdk
的bin
中,现在环境变成linux
了,应该也需要一些.so
之类的库,去研究一下官方说明:https://gdal.org/api/java/index.html
官方给的解决方案:在linux
上绑定java
编译GDAL/OGR
(https://trac.osgeo.org/gdal/wiki/GdalOgrInJavaBuildInstructionsUnix)
实际解决过程:
- 修改
/storage/software/gdal/gdal-3.3.2/swig/java/java.opt
内容,指定jdk
为:/opt/jdk1.8.221/
主要是加这一行:JAVA_HOME = /opt/jdk1.8.221/
,如下:
# Java Stuff
#JAVA_HOME = "C:\Program Files\Java\jdk1.6.0_16"
#JAVA_HOME = /usr/lib/jvm/java-6-openjdk/
#JAVA_HOME = /usr/lib/jvm/java-7-openjdk-amd64/
JAVA_HOME = /opt/jdk1.8.221/
JAVADOC=$(JAVA_HOME)/bin/javadoc
JAVAC=$(JAVA_HOME)/bin/javac
JAVA=$(JAVA_HOME)/bin/java
JAR=$(JAVA_HOME)/bin/jar
JAVA_INCLUDE=-I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux
编译:在
/storage/software/gdal/gdal-2.2.1/swig/java/
下执行# make
不要担心这个报错:./.libs/*.so error.
我实际上报了这个错:ant: Command not found
直接安装一下:# yum install ant
然后重新执行:# make
make
成功,在当前文件夹下生成了gdal.jar
和 一堆*.so
文件。添加动态链接库:
把/storage/software/gdal/gdal-3.3.2/swig/java/
下的.so
文件拷贝到/usr/local/lib/
下去:
执行:# cp /storage/software/gdal/gdal-3.3.2/swig/java/*.so /usr/local/lib/
因为之前安装gdal的时候,配置的~/.bashrc中库指向的是/usr/local/lib,看看:
[root@cumt java]# cat ~/.bashrc
# .bashrc
# User specific aliases and functions
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
export PATH=$PATH:/usr/local/bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
4.gdal.jar
打包到maven
:
-
gdal.jar
从linux
服务器上download到本机
/storage/software/gdal/gdal-2.2.1/swig/java/
下的gdal.jar
拷贝到本地F:\ckk\newCoalProject20201026\
目录下,重命名为gdal-linux-3.3.2.jar
- 然后把
jar
打到本机的maven
仓库中
# mvn install:install-file -Dfile=F:\ckk\newCoalProject20201026\gdal-linux-3.3.2.jar -DgroupId=com.hongyi -DartifactId=gdal-linux -Dversion=3.3.2 -Dpackaging=jar
- 然后在项目
pom
文件中引用:
<dependency>
<groupId>com.hongyi</groupId>
<artifactId>gdal-linux</artifactId>
<version>3.3.2</version>
</dependency>
完毕。