Java环境下GDAL / OGR环境配置与入门
- 0.概述
- 1.环境配置
- 1.1 开发环境下载
- 1.2 环境变量配置
- 1.3java工程配置
- 1.3.1新建Java工程
- 1.3.2添加GDAL的jar文件并构建
- 1.3.3 添加一个dll文件到工程
- 2.程序开发
- 2.1 界面搭建
- 2.2功能实现
0.概述
先放一个图标:
在尝试在C#环境下使用OGR之后,由于可参考的代码太少,并且C#环境下没办法构建可视化界面,并且C#会乱码。所以转向Java平台了,用Java开打GDAL和OGR的人比较多,网上代码也多,相对来说效率就更高一些了。
刚接触的时候用的还是Eclipse,还没用过IDEA,所以这篇文章也是基于Eclipse的,但是实际上两者差不多。下面是程序运行的情况,本示例仅打开Shapefile文件,关于界面显示,用到了GeoTools,后面学了之后介绍。
1.环境配置
关于环境配置网上的教程太多了,但是他们有一个共同的特点,就是过于条理性不足,并且对每一步的解释不够清晰,这篇文章我把步骤分为以下三个部分,希望能更容易被理解。
在进行下面的步骤之前,请确定自己已经配置了Java环境,并且Java的环境变量已经配置完毕。
1.1 开发环境下载
所需要下载的文件就只有一个,打开这个网站,找一个合适的版本下载即可 GDAL下载地址 ,我下载的是下图的版本,也可以选择其他版本,大差不差。
打开下载的压缩包,可以看到下面的文件
打开bin目录,众所周知,bin下面就是关键的文件了,一会这个目录要加到环境变量里面
打开gdal目录,这个时候就可以看到Java目录了,里面有两个文件,是用来配置Java工程的,1.3里面会用到
把这些文件解压到任意一个目录下面,之后就可以开始环境变量的配置了。
1.2 环境变量配置
网上关于环境配置的方法,大都是把刚下载文件里面的dll文件一股脑的放到Java目录下面,这样有个好处,就是十分方便,但是我感觉这样会一定程度的污染到Java环境,并且当自己不像再用GDAL的时候,想要把他的组件删掉,是一件很麻烦的事情。
从原理上面来说,直接把dll文件所在目录放到环境变量里面也是可以的,并且这个方法看起来更加符合逻辑。
因此具体做法是这样的
①右键桌面计算机,点击属性
②点击打开界面中右侧的高级系统设计
③点击环境变量按钮
④找到path,点击编辑
⑤点击新建按钮,把刚才下载文件解压目录的对文件夹加载进去,实际上不需要把这五个都加进去,但是为了避免以后再加,这次就索性全部添加进去。
⑥之后一路点确定,就完成环境变量配置了,下面创建一个Java工程,在Java里面进行一些配置。
1.3java工程配置
1.3.1新建Java工程
新建工程不多说了,直接New一个空的项目就行
1.3.2添加GDAL的jar文件并构建
新建一个lib文件夹,然后把1.1里面最后一张图片的后缀为jar的文件放进去
=>
之后右键这个gdal.jar,点击Build Path,把它添加到没模型构建起里面。
1.3.3 添加一个dll文件到工程
环境配置的最后一步,就是把gdalalljni.dll文件放到java的根目录下面,具体原理我也不知道,总之放就行了
=>
到这里环境变量配置工作就完成了,要使用GDAL,需要把组件在java文件开头引用一下
import org.gdal.ogr.*;
import org.gdal.gdal.*;
然后使用前把这两个东西注册一下
import org.gdal.ogr.*;
import org.gdal.gdal.*;
下面就可以开始使用了。
2.程序开发
2.1 界面搭建
java的swing界面虽然看起来美观度有些欠缺,但是用起来还是没什么问题的,下面搭建一个简单的界面,详细说明放在代码注释里面,界面上面的功能并没有全部实现,只需要关注打开Shapefile这一个功能即可:
//创建一个类,继承JFrame,实现ActionListener接口
public class Plugin_PostGIS extends JFrame implements ActionListener{
//注册一些公共组件,这其中包括了菜单栏按钮,表格,地图等等
JMenuItem openshapefile;
JMenuItem gdb;
JMenuItem mdb;
JMenuItem ConnectPostgres;
JMenuItem discardPostgres;
JMenuItem New;
JMenuItem Delet;
JMenuItem Import;
JMenuItem Select;
JMapPane mapPane;
JTable table;
MapLayerTable maptable;
ArcDataToPostgre myArcDataToPostgre;
Quickstart a;
Postgis_OGR pPostgis_OGR;
JComboBox filecombox = new JComboBox();
JComboBox datacombox = new JComboBox();
JButton jb2;
JButton jb1;
//注册GDAL
public Plugin_PostGIS() {
org.gdal.gdal.gdal.AllRegister();
org.gdal.ogr.ogr.RegisterAll();
// TODO Auto-generated method stub
Init();
}
private static Map DBMAP = new HashMap<String, Object>() {
{
put("dbtype", "postgis");
put("host", "localhost");
put("port", 5432);
put("schema", "public");
put("database", "little_c_sharp");
put("user", "postgres");
put("passwd", "107530");
}
};
public void Init() {
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
Dimension dm = Toolkit.getDefaultToolkit().getScreenSize();
this.setBounds(dm.width/2-300, dm.height/2-300, 700, 700);
this.setLayout(new BorderLayout());
//菜单栏目
JMenuBar menuBar = new JMenuBar();
JMenu menufile = new JMenu("File");
JMenu menudatabase = new JMenu("Database");
openshapefile = new JMenuItem("打开OpenShapefile文件");
gdb = new JMenuItem("打开gdb数据库");
mdb = new JMenuItem("打开mdb数据库");
ConnectPostgres = new JMenuItem("连接Postgres");
discardPostgres = new JMenuItem("断开Postgres");
New = new JMenuItem("新建数据表");
Delet = new JMenuItem("删除数据表");
Import = new JMenuItem("导入当前数据");
Select = new JMenuItem("查询数据");
openshapefile.addActionListener(this);
Import.addActionListener(this);
ConnectPostgres.addActionListener(this);
discardPostgres.addActionListener(this);
menuBar.add(menufile);
menuBar.add(menudatabase);
menufile.add(openshapefile);
menufile.add(gdb);
menufile.add(mdb);
menudatabase.add(ConnectPostgres);
menudatabase.add(discardPostgres);
menudatabase.add(New);
menudatabase.add(Delet);
menudatabase.add(Import);
menudatabase.add(Select);
//地图容器
mapPane = new JMapPane();
mapPane.setBackground(Color.WHITE);
mapPane.setBorder(BorderFactory.createLineBorder(Color.BLACK));
//属性表
table=new JTable();
JScrollPane tablepanel=new JScrollPane(table);
//maptable=new MapLayerTable(mapPane);
//左侧容器
JPanel leftJPanel=new JPanel();
leftJPanel.setLayout(new BorderLayout());
JPanel lefttopJPanel=new JPanel();
JPanel leftbuttonJPanel=new JPanel();
jb1=new JButton("显示");
jb2=new JButton("读取");
jb2.addActionListener(this);
leftJPanel.add(lefttopJPanel,BorderLayout.NORTH);
leftJPanel.add(leftbuttonJPanel,BorderLayout.SOUTH);
lefttopJPanel.setLayout(new BorderLayout());
leftbuttonJPanel.setLayout(new BorderLayout());
lefttopJPanel.add(jb1,BorderLayout.CENTER);
lefttopJPanel.add(filecombox,BorderLayout.NORTH);
leftbuttonJPanel.add(jb2,BorderLayout.CENTER);
leftbuttonJPanel.add(datacombox,BorderLayout.NORTH);
JPanel top = new JPanel();
top.setLayout(new BorderLayout());
top.add(mapPane,BorderLayout.CENTER);
top.add(leftJPanel,BorderLayout.WEST);
SetComposeSize(dm,tablepanel,top,mapPane,leftJPanel,lefttopJPanel,leftbuttonJPanel);
//添加控件到主界面
this.setJMenuBar(menuBar);
this.add(top,BorderLayout.CENTER);
this.add(tablepanel,BorderLayout.SOUTH);
}
public void SetComposeSize(Dimension dm,JScrollPane jp,JPanel t,JMapPane jm,JPanel l,JPanel lt,JPanel jb) {
jp.setSize(dm.width,(int)(dm.height*0.3));
t.setSize(dm.width,(int)(dm.height*0.7));
Dimension dtd=l.getSize();
jm.setSize((int)(dtd.width*0.8),(int)(dtd.height));
l.setSize((int)(dtd.width*0.2),(int)(dtd.height));
Dimension ld=l.getSize();
lt.setSize(ld.width,(int)(ld.height*0.5));
jb.setSize(ld.width,(int)(ld.height*0.5));
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource()==openshapefile) {
JFileChooser chooser=new JFileChooser();
int returnvalue =chooser.showOpenDialog(this);
if(returnvalue==JFileChooser.APPROVE_OPTION) {
//File f = chooser.getSelectedFile();
File f = new File("E:/CodeStudy/CsharpConPG/SHp/四省.shp");
if(a==null) {
a = new Quickstart();
}
String[] columnameStrings = a.openfileCol(f.getAbsolutePath());
String[][] data = a.openfile(f.getAbsolutePath());
DefaultTableModel model;
model = new DefaultTableModel(data, columnameStrings);
table.setModel(model);
this.mapPane.setMapContent(a.getMapContent(f));
}
}
else if(e.getSource()==ConnectPostgres) {
if(a==null) {
a = new Quickstart();
}
pPostgis_OGR=new Postgis_OGR("PG:dbname=little_c_sharp host=localhost port=5432 user=postgres password=107530");
myArcDataToPostgre = new ArcDataToPostgre(this.DBMAP);
List<String> names = pPostgis_OGR.getLayerNames();
for (int i = 0; i < names.size(); i++) {
this.datacombox.addItem(names.get(i));
}
}
else if(e.getSource()==Import) {
myArcDataToPostgre.importGdbToDatabaseSingal(a.currentDataSource.GetLayer(0), null);
}
else if(e.getSource()==discardPostgres) {
myArcDataToPostgre.disconnectdatabase();
}
else if(e.getSource()==jb2) {
Layer nowLayer = pPostgis_OGR.getLayerByname(datacombox.getSelectedItem().toString());
String filepathString = pPostgis_OGR.LayerToGeoJson(nowLayer);
File geojsonFile = new File(filepathString);
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String[] columnameStrings = a.openfileCol(nowLayer);
String[][] data = a.openfile(nowLayer);
DefaultTableModel model;
model = new DefaultTableModel(data, columnameStrings);
table.setModel(model);
this.mapPane.setMapContent(a.getMapContent(geojsonFile));
//this.mapPane.setMapContent(a.getMapContent(f));
}
}
}
2.2功能实现
下面是两个方法,主要是获取属性表的表头和数据,表头用一个数组表示,数据用一个二维数组表示,代码解释放在注释里面,这些数据主要用来创建DefaultTableModel用来作为JTable的数据源。
//这个函数用来获取表头
public static String[] openfileCol(String filename) {
//打开shapefile
DataSource ds = ogr.Open(filename,1);
currentDataSource=ds;
for (int i=0;i< ds.GetLayerCount(); i++)
{
org.gdal.ogr.Layer layer = ds.GetLayerByIndex(i);
//获取表头信息
FeatureDefn pFeatureDefn = layer.GetLayerDefn();
String[] outst = new String[pFeatureDefn.GetFieldCount()];
//遍历表头,存储到outst里面用于返回
for (int j = 0; j < pFeatureDefn.GetFieldCount(); j++)
{
FieldDefn fie = pFeatureDefn.GetFieldDefn(j);
outst[j]=fie.GetName();
//MessageBox.Show(pFeatureDefn.GetFieldDefn(j).GetNameRef().ToString());
//MessageBox.Show(pFeatureDefn.GetFieldDefn(j).GetTypeName().ToString());
}
return outst;
}
return null;
}
//这个函数用来获取属性表里面的数据,输入shapefile文件名,返回存储了数据的二维数组
public static String[][] openfile(String filename) {
DataSource ds = ogr.Open(filename,1);
currentDataSource=ds;
String outst = "";
for (int i=0;i< ds.GetLayerCount(); i++)
{
org.gdal.ogr.Layer layer = ds.GetLayerByIndex(i);
FeatureDefn pFeatureDefn = layer.GetLayerDefn();
String[][] dataut =new String[(int)layer.GetFeatureCount()][pFeatureDefn.GetFieldCount()];
for (int j = 0; j < layer.GetFeatureCount(1); j++)
{
//获取一个要素
Feature feature = layer.GetFeature(j);
//遍历各个要素的属性,存储到数组里面
for(int k=0;k< pFeatureDefn.GetFieldCount(); k++)
{
dataut[j][k] = feature.GetFieldAsString(k);
}
outst+="\n";
}
return dataut;
}
return null;
}