Ubuntu下使用CMake编译安装GDAL3.6.1(3.8.4)、链接Java(Java21)、加入FileGDB驱动
***
2024-08-06,GDAL 3.9.1
版本详细编译过程以及一键编译脚本,最新 博客地址
写在前面
第一次Linux下编译源代码,遇到了很多坑,差点就放弃了,看了一下网上的教程都是老版本的,不是使用 CMake
方式的编
译,研究了很久总算弄出来了,希望能在思路上帮到大家,有问题可以留言,我会的帮解决
不会的只能再查了,如果我的搭建方式有问题,后续我会更新这篇博客的内容,
版本特别需求
Ubuntu 16.04 # 因为FileGDB驱动最高只支持Ubuntu16.04,更高的不支持了,如果你不用FileGDB驱动,更高版本也是可以的
jdk1.8
cmake 3.23.0 # 因为在Ubuntu16.04上直接apt安装的话它的版本GDAL编译不支持,所以得我们自己安装更高版本
gcc 5.x
sqlite3 # 因为proj是依赖sqlite的,所以必须得安装
proj6 # 然后GDAL又是依赖proj的,所以proj又必须得安装,GDAL3.6.x以上3.7.x以下都得使用最低proj6
FileGDB 1.5.1-64gcc51 # 使用gcc版本最低不得低于5.x
# 其他需求在下面安装依赖的时候默认最新就行
1、更新源,创建目录
可以直接复制粘贴然后运行,如果你想一条一条的运行就把 &&
去掉。另外不太建议换成国内的源,可能会有
一些依赖找不到对应的版本,反正速度也不是特别慢,将就用吧。
apt update &&
mkdir /app &&
cd /app &&
mkdir java gdal filegdb proj cmake
2、复制各种包到容器免得下载
docker cp FileGDB_API_1_5_1-64gcc51.tar.gz ub:/app/filegd
docker cp jdk-8u202-linux-x64.tar.gz ub:/app/java
docker cp cmake-3.23.0.tar.gz ub:/app/cmake
docker cp gdal-3.6.1.tar.gz ub:/app/gdal
#docker cp 包 容器名:/app/对应的目录
包的下载地址:
FileGDB,这是GitHub的地址,进去后自己找包,找到后直接点包,会进入具体的代码页面,
但是这是压缩包,看不到代码,右上角有个下载按钮直接下载就行,或者你找得到官网上的下载地址下载也行:
https://github.com/Esri/file-geodatabase-api/tree/master/FileGDB_API_1.5.1
jdk不提供,自己下,用的jdk1.8
cmake:
https://cmake.org/files/v3.23/cmake-3.23.0.tar.gz
gdal官方源代码包,可以去官方网站下载,也可以去GitHub上拉,我选择官网下:
https://github.com/OSGeo/gdal/releases/download/v3.6.1/gdal-3.6.1.tar.gz
3、安装各种依赖,有的用得上,有的用不上,难得分辨了
apt install -y build-essential wget vim unzip swig ant sqlite3 libsqlite3-dev \
pkg-config libopenjp2-7 libcairo2 libpng16-16 libjpeg-turbo8 libgif7 liblzma5 \
libgeos-c1v5 libxml2 libexpat1 libnetcdf-c++4 netcdf-bin libspatialite7 \
librasterlite2-1 gpsbabel libhdf4-0-alt poppler-utils \
libfreexl1 unixodbc mdbtools liblcms2-2 libpcre3 libcrypto++-dev libfyba0 \
libkmlbase1 libkmlconvenience1 libkmldom1 libkmlengine1 libkmlregionator1 \
libkmlxsd1 libzstd1 bash bash-completion libpq5 libblosc1 \
liblz4-1 libbrotli1 libarchive13 libssl-dev libgeos-3.5.0 libxerces-c3.1 libogdi3.2
#在下载的时候,如果有提示报错包没找到包不存在,就用 apt search xxx 来搜索xxx包,看下有没有其他版本的替代,用最新的就行
4、安装 Java
apt-get remove openjdk-* &&
cd /app/java/ &&
tar -zxvf jdk-8u202-linux-x64.tar.gz &&
mv jdk1.8.0_202/ jdk &&
rm jdk-8u202-linux-x64.tar.gz &&
vim ~/.bashrc
# 到这步没报错的话会进入一个文件,直接跳到最后,按A键编辑文件,添加下面这两个export到最后
export JAVA_HOME=/app/java/jdk
export PATH=$PATH:$JAVA_HOME/bin
# esc、 :(冒号) 、wq、回车保存
source ~/.bashrc &&
java -version
# 版本出现就正常,没出现或者报错就百度吧,这是Linux安装jdk,教程很多
5、安装 CMake
,Ubuntu16.04
的CMake版本GDAL编译不支持,我们自己找版本安装
# 先卸载系统上已经存在的CMake
apt remove cmake &&
apt autoremove &&
rm -rf /usr/bin/cmake* &&
rm -rf /usr/local/bin/cmake* &&
rm -rf /usr/share/cmake* &&
cd /app/cmake &&
# 解压
tar -zxvf cmake-3.23.0.tar.gz &&
cd cmake-3.23.0 &&
# 编译
./configure &&
make -j10 &&
# 安装
make install &&
cmake -version
# 出现版本正常:
# cmake version 3.23.0
# CMake suite maintained and supported by Kitware (kitware.com/cmake).
6、安装 PROJ6
,GDAL
的底层依赖 PROJ
cd /app/proj &&
# 下载包
wget http://download.osgeo.org/proj/proj-6.3.1.zip &&
# 包是zip格式的,要用unzip命令解压
unzip proj-6.3.1.zip &&
cd proj-6.3.1 &&
# 编译
./configure &&
make -j10 &&
#安装
make install &&
# 刷新配置
ldconfig &&
proj --version
# 出现版本正常:
# Rel. 6.3.1, February 10th, 2020
# <proj>:
# invalid option: --
# program abnormally terminated
7、配置 FileGDB
驱动
cd /app/filegdb &&
tar -zxvf FileGDB_API_1_5_1-64gcc51.tar.gz &&
chown -R root:root FileGDB_API-64gcc51 &&
mv FileGDB_API-64gcc51 /usr/local/FileGDB_API &&
rm -rf /usr/local/FileGDB_API/lib/libstdc++* &&
cp /usr/local/FileGDB_API/lib/* /usr/lib/ &&
cp /usr/local/FileGDB_API/include/* /usr/include
# 这些命令建议直接复制,不要改任何东西,我一点一点试出来的,都是血和泪,
# 命令没问题,就是包所在的路径有问题,最好按照这个路径格式来,暂时不清楚是什么导致的
8、编译安装GDAL
# 到主要步骤了,请确定你的 swig、ant、proj、java安装正常并且版本正确
proj --version
ant -version
swig -version
java -version
echo $JAVA_HOME
cd /app/gdal &&
# 解压
tar -zxvf gdal-3.6.1.tar.gz &&
cd gdal-3.6.1 &&
# 创建一个build文件夹,这是官方建议的,别乱改
mkdir build &&
cd build &&
# DFileGDB_INCLUDE_DIR 意思是指定FileGDb驱动要用的头文件.h所在的文件夹,DFileGDB_LIBRARY 是FielGDB所需库文件所在的路径
cmake -DFileGDB_INCLUDE_DIR=/usr/local/FileGDB_API/include/ -DFileGDB_LIBRARY=/usr/lib/libFileGDBAPI.so -DCMAKE_BUILD_TYPE=Release ..
# DCMAKE_BUILD_TYPE=Release 默认写法,提升编译效率的
# 执行完成无误的输出应该是:
# -- Configuring done
# -- Generating done
# -- Build files have been written to: /app/gdal/gdal-3.6.1/build
# 并且没有任何报错
# 正式编译
cmake --build .
#中间有爆红不用管,只要结尾处100%的地方没有报错没有爆红就行
# 安装
cmake --build . --target install
# 没有报错就行
# 打开bash shell的配置文件
vim ~/.bashrc
# 如果你到现在是跟着我的目录来的话,加上这句话。如果你改了目录,那么就要对应修改路径
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
# wq保存,source使配置生效
source ~/.bashrc
gdalinfo --version
# 如果打印出来的版本信息是这样那恭喜你完成了最凶险的一步:
# GDAL 3.6.1, released 2022/12/14
# 如果报错,请将/app/gdal/gdal-3.6.1/build 下的libgdal.*文件复制到/usr/local/lib下
cp /app/gdal/gdal-3.6.1/build/libgdal.* /usr/local/lib/
# 再试试 gdalinfo --version
9、配置GDAL
和Java
的链接(很坑)
# 进入swig文件夹
cd /app/gdal/gdal-3.6.1/build/swig/
# 如果有java文件夹,那么恭喜你,胜利就在眼前
# 我先说有java文件夹的怎么处理
# 有java文件夹则表示java的链接被编译成功,你进入java文件夹,应该能找到两个文件
cd java
ls
# CMakeFiles build javadoc.zip tmp_test
# CTestTestfile.cmake cmake_install.cmake libgdalalljni.so
# Makefile gdal.jar org
# add_javadoc java org_patched
# gdal.jar 和 libgdalalljni.so ,这两个是关键文件,jar文件是给你开发时候放到IDEA里面当maven依赖用的
# libgdalalljni.so 这个文件夹你要放到 /usr/local/lib 下,这个路径就是我们刚才配置环境变量LD_LIBRARY_PATH的那个路径
cp libgdalalljni.so /usr/local/lib
# 如果你的swig下没有java这个文件夹,那么请再次检查你的 ant和swig 有没有安装好
# 没有出现java文件夹,多半是ant或swig安装有问题,要么就是java环境有问题,因为gdal在编译的时候是自动的,
# 你环境齐全的话就会自动给你把java的链接编译出来,实在不行就重来吧
ant -version
swig -version
到这步基本就算完了,写一个java测试
package org.example;
import org.gdal.gdal.gdal;
import org.gdal.ogr.*;
public class Main {
public static void main(String[] args) {
System.out.println("-------------------- start to load gdal .... --------------------");
//获取数据源开始读文件
gdal.AllRegister();
// 为了支持中文路径,请添加下面这句代码
gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
//为了是属性表字段支持中文,请添加下面代码
gdal.SetConfigOption("FILEGDB_ENCODING", "CP936");
//获取驱动
Driver driver = ogr.GetDriverByName("FileGDB");
if (driver == null){
System.out.println("-------------------- driver is null .... --------------------");
return;
}
//获取数据源
DataSource dataSource = driver.Open("/app/test.gdb");
if (dataSource == null){
System.out.println("-------------------- dataSource is null .... --------------------");
}else {
for (int i = 0; i < dataSource.GetLayerCount(); i++) {
//获取图层
Layer layer = dataSource.GetLayer(i);
if (layer == null){
System.out.println("-------------------- layer is null,continue next layer --------------------");
continue;
}
for (long l = 0; l < layer.GetFeatureCount(); l++) {
//获取要素
Feature feature = layer.GetNextFeature();
if (feature == null){
System.out.println("-------------------- feature is null at fid :" + l + " --------------------");
continue;
}
//直接打印矢量数据
System.out.println(feature.GetGeometryRef().ExportToJson());
}
}
System.out.println("============== SUCCESS ==============");
System.out.println("============== END ==============");
}
}
}
如果以上代码输出没有报错:
Native library load failed.
java.lang.UnsatisfiedLinkError: no gdalalljni in java.library.path
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65)
Caused by: java.lang.UnsatisfiedLinkError: org.gdal.gdal.gdalJNI.AllRegister()V
at org.gdal.gdal.gdalJNI.AllRegister(Native Method)
at org.gdal.gdal.gdal.AllRegister(gdal.java:684)
at org.example.Main.main(Main.java:13)
... 8 more
那就是成了,基本上能用了,我的也就到这步,还没进行过深度测试,有问题我会回来及时更改的
顺便再提一句,如果编译GDAL要加上java的链接,那么 swig
和 ant
很重要,一定要确保这两个是没问题的
其他报错
1、这个报错主要体现在明明指定了FileGDB的路径并且库文件头文件都在,但就是读取不了导致GDAL一直编译不过,那么没错了就是这个错系统版本不支持,也就是你用了File GDB的驱动,但是你没用Ubuntu16.04,FileGDB不支持高版本的Ubuntu,最高支持16.04。这是GDAL的官方开发人员说的,不是我杜撰的。
CMake Error in CMakeLists.txt:
IMPORTED_LOCATION not set for imported target "FILEGDB::FileGDB"
configuration "Release".
2、这个错可以参考第9步:
gdalinfo --version
gdalinfo: error while loading shared libraries: libgdal.so.32: cannot open shared object file: No such file or directory
我报错了一堆,暂时只记得这两个,想起来会继续补充。
------------------------------------------------------------------------ 分界线 ------------------------------------------------------------------------
2023-11-14更新:
今天把Dockerfile
写出来了,需要的直接复制就行,注意将所需的文件都放在 ./dependency/
下,当前目录就放Dockerfile
文件
FROM ubuntu:16.04
LABEL maintainer="hyz <[email protected]>"
RUN apt update && mkdir /app && cd /app && mkdir java gdal filegdb proj cmake && \
apt install -y build-essential wget vim unzip swig ant sqlite3 libsqlite3-dev \
pkg-config libopenjp2-7 libcairo2 libpng16-16 libjpeg-turbo8 libgif7 liblzma5 \
libgeos-c1v5 libxml2 libexpat1 libnetcdf-c++4 netcdf-bin libspatialite7 \
librasterlite2-1 gpsbabel libhdf4-0-alt poppler-utils \
libfreexl1 unixodbc mdbtools liblcms2-2 libpcre3 libcrypto++-dev libfyba0 \
libkmlbase1 libkmlconvenience1 libkmldom1 libkmlengine1 libkmlregionator1 \
libkmlxsd1 libzstd1 bash bash-completion libpq5 libblosc1 \
liblz4-1 libbrotli1 libarchive13 libssl-dev libgeos-3.5.0 libxerces-c3.1 libogdi3.2
COPY ./dependency/FileGDB_API_1_5_1-64gcc51.tar.gz /app/filegdb
COPY ./dependency/jdk-8u202-linux-x64.tar.gz /app/java
COPY ./dependency/cmake-3.23.0.tar.gz /app/cmake
COPY ./dependency/gdal-3.6.1.tar.gz /app/gdal
RUN cd /app/java/ && tar -zxvf jdk-8u202-linux-x64.tar.gz && \
mv jdk1.8.0_202/ jdk && rm jdk-8u202-linux-x64.tar.gz
ENV JAVA_HOME=/app/java/jdk
ENV PATH=$PATH:$JAVA_HOME/bin
RUN apt remove cmake && apt autoremove && rm -rf /usr/bin/cmake* && rm -rf /usr/local/bin/cmake* && \
rm -rf /usr/share/cmake* && cd /app/cmake && tar -zxvf cmake-3.23.0.tar.gz && cd cmake-3.23.0 && \
./configure && make -j10 && make install
RUN cd /app/proj && wget http://download.osgeo.org/proj/proj-6.3.1.zip && unzip proj-6.3.1.zip && \
cd proj-6.3.1 && ./configure && make -j10 && make install && ldconfig
RUN cd /app/filegdb && tar -zxvf FileGDB_API_1_5_1-64gcc51.tar.gz && \
chown -R root:root FileGDB_API-64gcc51 && mv FileGDB_API-64gcc51 /usr/local/FileGDB_API && \
rm -rf /usr/local/FileGDB_API/lib/libstdc++* && cp /usr/local/FileGDB_API/lib/* /usr/lib/ && \
cp /usr/local/FileGDB_API/include/* /usr/include
RUN cd /app/gdal && tar -zxvf gdal-3.6.1.tar.gz && cd gdal-3.6.1 && mkdir build && cd build && \
cmake -DFileGDB_INCLUDE_DIR=/usr/local/FileGDB_API/include/ -DFileGDB_LIBRARY=/usr/lib/libFileGDBAPI.so -DCMAKE_BUILD_TYPE=Release .. \
&& cmake --build . && cmake --build . --target install
ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
RUN cd /app/gdal/gdal-3.6.1/build/swig/java && cp libgdalalljni.so /usr/local/lib
完事后直接 docker build
构建就行:
docker build -t gdal_java-env:1.0 .
注意后面的 .
别丢了
------------------------------------------------------------------- 分界线 2023-03-26 更新 --------------------------------------------------------------------
我又回来了,今天回来是对上面的博客有大更新,由于最近有GDB数据读取提速的需求,之前都是用
Java8
的多线程来读取GDB中的Layer
、Feature
的,我也不知道怎么突然就盯上了Java21
的虚拟线程
了,于是将环境更新,来跑新代码。
至于Java21
读取GDB速率的提升,我也不晓得,没测试,但是我很有信心提速了,关于Java21
,请看我另外一篇博客,讲Java21
的虚拟线程的,链接放在这了。
我也不磨叽了,直接放
Dockerfile
:
FROM ubuntu:16.04
LABEL maintainer="hyz <[email protected]>"
RUN apt-get update && mkdir /app && cd /app && mkdir java gdal filegdb proj project cmake && \
apt-get install -y build-essential wget vim unzip swig ant sqlite3 libsqlite3-dev \
pkg-config libopenjp2-7 libcairo2 libpng16-16 libjpeg-turbo8 libgif7 liblzma5 \
libgeos-c1v5 libxml2 libexpat1 libnetcdf-c++4 netcdf-bin libspatialite7 \
librasterlite2-1 gpsbabel libhdf4-0-alt poppler-utils \
libfreexl1 unixodbc mdbtools liblcms2-2 libpcre3 libcrypto++-dev libfyba0 \
libkmlbase1 libkmlconvenience1 libkmldom1 libkmlengine1 libkmlregionator1 \
libkmlxsd1 libzstd1 bash bash-completion libpq5 libblosc1 \
liblz4-1 libbrotli1 libarchive13 libssl-dev libgeos-3.5.0 libxerces-c3.1 libogdi3.2
COPY ./dependency/FileGDB_API_1_5_1-64gcc51.tar.gz /app/filegdb
COPY ./dependency/jdk-21_linux-x64_bin.tar.gz /app/java
COPY ./dependency/cmake-3.23.0.tar.gz /app/cmake
COPY ./dependency/gdal-3.8.4.tar.gz /app/gdal
RUN cd /app/java/ && tar -zxvf jdk-21_linux-x64_bin.tar.gz && \
mv jdk-21.0.2/ jdk && rm jdk-21_linux-x64_bin.tar.gz
ENV JAVA_HOME=/app/java/jdk
ENV PATH=$PATH:$JAVA_HOME/bin
RUN apt-get remove cmake && apt autoremove && rm -rf /usr/bin/cmake* && rm -rf /usr/local/bin/cmake* && \
rm -rf /usr/share/cmake* && cd /app/cmake && tar -zxvf cmake-3.23.0.tar.gz && cd cmake-3.23.0 && \
./configure && make -j16 && make install
RUN cd /app/proj && wget http://download.osgeo.org/proj/proj-6.3.1.zip && unzip proj-6.3.1.zip && \
cd proj-6.3.1 && ./configure && make -j10 && make install && ldconfig
RUN cd /app/filegdb && tar -zxvf FileGDB_API_1_5_1-64gcc51.tar.gz && \
chown -R root:root FileGDB_API-64gcc51 && mv FileGDB_API-64gcc51 /usr/local/FileGDB_API && \
rm -rf /usr/local/FileGDB_API/lib/libstdc++* && cp /usr/local/FileGDB_API/lib/* /usr/lib/ && \
cp /usr/local/FileGDB_API/include/* /usr/include
RUN cd /app/gdal && tar -zxvf gdal-3.8.4.tar.gz && cd gdal-3.8.4 && mkdir build && cd swig/java && \
sed -i 's/debug="on" source="7" target="7"/debug="on" source="8" target="8"/g' build.xml && cd ../../build && \
cmake -DFileGDB_INCLUDE_DIR=/usr/local/FileGDB_API/include/ -DFileGDB_LIBRARY=/usr/lib/libFileGDBAPI.so \
-DCMAKE_BUILD_TYPE=Release .. && cmake --build . && cmake --build . --target install
ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
RUN cd /app/gdal/gdal-3.8.4/build/swig/java && cp libgdalalljni.so /usr/local/lib
记得去一开始我给的下载地址中,将所需的包下载下来放到
./dependency
,也就是当前目录下的dependency
文件夹中,或者你可以改Dockerfile
中那几个COPY
所指的那个地址。
变版本的包:jdk-21_linux-x64_bin.tar.gz
、gdal-3.8.4.tar.gz
,没错,用了Java21
了,gdal
也用了3.8.4
了,哦对了,还有个严重的问题,你可能会遇到,也可能遇不到,用我的Dockerfile
的话应该遇不到,我提一嘴把。
如果在构建时遇到错误:
[ 93%] Generating gdal.jar, build/maven/gdal-3.8.4.jar, build/maven/gdal-3.8.4-sources.jar,
build/maven/gdal-3.8.4.pom, build/maven/gdal-3.8.4-javadoc.jar
Buildfile: /app/gdal/gdal-3.8.4/swig/java/build.xml
init:
[echo] version = 3.8.4
compile:
[mkdir] Created dir: /app/gdal/gdal-3.8.4/build/swig/java/build/classes
[javac] Compiling 88 source files to /app/gdal/gdal-3.8.4/build/swig/java/build/classes
[javac] warning: [options] bootstrap class path not set in conjunction with -source 7
[javac] error: Source option 7 is no longer supported. Use 8 or later.
[javac] error: Target option 7 is no longer supported. Use 8 or later.
那么没错,这是
GDAL源码
的问题,我去GitHub上查了,官方源码中gdal/swig/java /build.xml
中有一段是这样的:
<target name="compile" depends="init" description="Compile the source files.">
<mkdir dir="${build_dir}/build/classes"/>
<javac srcdir="${build_dir}/org" destdir="${build_dir}/build/classes"
debug="on" source="7" target="7"
includeantruntime="false" deprecation="true">
</javac>
<echo>compilation complete</echo>
</target>
看到了嘛,它支持的最低版本是
Java7
,最新的GDAL3.8.4
中已经改为了:
<target name="compile" depends="init" description="Compile the source files.">
<mkdir dir="${build_dir}/build/classes"/>
<javac srcdir="${build_dir}/org" destdir="${build_dir}/build/classes"
debug="on" source="8" target="8"
includeantruntime="false" deprecation="true">
</javac>
<echo>compilation complete</echo>
</target>
出现这个问题的原因是,你下载的
GDAL3.8.4
可能不是最新的debug="on" source="8" target="8"
,我也不知道为啥会这样,可能是错乱了,我搞清楚再补充吧,总之在我的Dockerfile
中解决了,倒数第二个RUN
中:
RUN cd /app/gdal && tar -zxvf gdal-3.8.4.tar.gz && cd gdal-3.8.4 && mkdir build && cd swig/java && \
sed -i 's/debug="on" source="7" target="7"/debug="on" source="8" target="8"/g' build.xml
有一个
sed -i 's/debug="on" source="7" target="7"/debug="on" source="8" target="8"/g' build.xml
,这句的意思就是在修改导致错误的这个包中的这个不正确的代码,将debug="on" source="7" target="7"
改为debug="on" source="8" target="8"
,总之这样改就没问题了,构建就能成功了。
docker build -t gdal_java-env:2.0 .
还是别忘了后面的那个
.
哎呀,我总是忘记事情,都发布了,又回来改:
*
还有一个问题,根据上面的流程构建好后,在容器内/usr/bin
中有一个java
文件,我也不知道哪一步多出来的,需要把这个文件删掉,不然你在这个镜像生成的容器内运行java -version
,你会发现还是Java8
,我们得删掉这个Java文件:
rm /usr/bin/java
再次运行
java -version
如果是Java21
就没问题了
构建成功了,写一个
Java21虚拟线程
使用GDAL3.8.4
读取Feature
的测试代码:
public static void main(String[] args) throws ExecutionException, InterruptedException {
long startTime = System.nanoTime();
gdal.AllRegister();
gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
Driver driver = ogr.GetDriverByName("OpenFileGDB");
DataSource dataSource = driver.Open("F:\\dev_file\\test_file\\test.gdb");
System.out.println("开始表演...");
final int slices = 6; //分片读取
var futures = new ArrayList<Future<?>>();
try (var exe = Executors.newVirtualThreadPerTaskExecutor()){
for (int i = 0; i < dataSource.GetLayerCount(); i++) {
var layer = dataSource.GetLayer(i);
final long featureCount = layer.GetFeatureCount();
final long sliceSize = featureCount / slices;
for (int j = 0; j < slices; j++) {
int finalI = j;
futures.add(exe.submit(() -> {
var cpLayer = finalI == 0 ?
layer : driver.Open("F:\\dev_file\\test_file\\test.gdb").GetLayer(0);
long start = finalI * sliceSize;
long end = (finalI < slices - 1) ? start + sliceSize : featureCount;
cpLayer.SetNextByIndex(start);
for (long z = start; z < end; z++) {
Feature feature = cpLayer.GetNextFeature();
feature.GetGeometryRef().ExportToJson();
feature.delete();
}
}));
}
}
}
for (Future<?> future : futures) {
future.get();
}
dataSource.delete();
long endTime = System.nanoTime();
long duration = (endTime - startTime); // 单位为纳秒
System.out.println("耗时: " + duration / 1000000 + "毫秒");
}
关于这个测试代码,后续我有时间会再详细的写一片新的博客解释的,这里面遇到的问题也很多。包括
分片
、单图层的线程
问题、I/O密集
、CPU密集
等问题,还有我试过很多的读取方法,包括生产者
、消费者
模型。
忘了说了,我一开始原打算使用
C++
来实现上面的这个代码功能的,但是我不太熟C++
,对于C++21
中的协程
更不熟了,
普通的C++多线程
相对于Java的虚拟线程
来说的话,提升并不是特别巨大,于是便又回到Java。
2023-03-26更新
后面想起其他的我会继续更新的。