Java调用Gdal写Esri ShapeFile文件工具类

本文详细介绍了如何通过GDAL API创建ShapeFile,包括创建EsriShapeFile驱动、数据源、图层、字段和要素,以及如何从Excel读取数据并生成点状矢量文件。重点在于简化工具类代码和步骤说明。
摘要由CSDN通过智能技术生成

目录

关于ShapeFile

创建ShapeFile的逻辑

创建实体类


关于ShapeFile

可以参考百度百科https://baike.baidu.com/item/shapefile%E6%96%87%E4%BB%B6/11041662?fr=aladdin

这里需要说的就是本文档生成的ShapeFile包含.shp、.shx、.dbf、.prj四类文件

创建ShapeFile的逻辑

根据GDAL3.2的API文档可知,创建ShapeFile的过程为:

1、创建Esri ShapeFile驱动类。

2、创建数据源类;

3、在数据源类上创建图层类;

4、在图层类上创建字段类、要素类;

5、保存数据源。

这里附一个gdal.jar的maven标签

<dependency>
    <groupId>org.gdal</groupId>
    <artifactId>gdal</artifactId>
    <version>3.3.0</version>
    <type>pom</type>
</dependency>

gdal是用C++编写的,可执行文件下载https://www.gisinternals.com/,里面也包含gdal的jar包,通过gdalalljni.dll调用底层的代码。

创建实体类

为了简化工具类的代码,这里先创建实体类:

字段实体类

package com.util.entity;

public class ShapeTitle {

	/**
	 * 字段名称
	 */
	private String name;
	
	/**
	 * 字段长度
	 */
	private int length;
	
	/**
	 * 字段类型
	 */
	private int type;

	public ShapeTitle(String name, int type) {
		this.name = name;
		this.type = type;
	}

	public ShapeTitle(String name, int length, int type) {
		this.name = name;
		this.length = length;
		this.type = type;
	}

	public ShapeTitle() {
		super();
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getLength() {
		return length;
	}

	public void setLength(int length) {
		this.length = length;
	}

	public int getType() {
		return type;
	}

	public void setType(int type) {
		this.type = type;
	}

}

ShapeFile实体类

package com.util.entity;

import java.util.List;
import java.util.Map;

import org.gdal.osr.SpatialReference;

public class ShapeFileBean {

	/**
	 * 空间参考
	 */
	private SpatialReference Sptref; 
	
	/**
	 * 字段实体类
	 */
	private List<ShapeTitle> title;
	
	/**
	 * 矢量图层的要素类
	 */
	private List<Map<Integer,Object>> feature;

	public ShapeFileBean() {

	}

	public List<ShapeTitle> getTitle() {
		return title;
	}

	public void setTitle(List<ShapeTitle> title) {
		this.title = title;
	}

	public List<Map<Integer,Object>> getFeature() {
		return feature;
	}

	public void setFeature(List<Map<Integer,Object>> feature) {
		this.feature = feature;
	}

	public SpatialReference getSptref() {
		return Sptref;
	}

	public void setSptref(SpatialReference sptref) {
		Sptref = sptref;
	}

}

工具类

package com.util;

import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Vector;

import org.gdal.gdal.gdal;
import org.gdal.ogr.DataSource;
import org.gdal.ogr.Driver;
import org.gdal.ogr.Feature;
import org.gdal.ogr.FeatureDefn;
import org.gdal.ogr.FieldDefn;
import org.gdal.ogr.Geometry;
import org.gdal.ogr.Layer;
import org.gdal.ogr.ogr;
import com.util.entity.ShapeFileBean;
import com.util.entity.ShapeTitle;

public class ShapeFileWriter {
	
	/**
	 * 文件名称
	 */
	private String FileName;

	/**
	 * 驱动名称
	 */
	private String strDriverName = "ESRI Shapefile";

	/**
	 * 驱动
	 */
	private Driver oDriver;
	
	/**
	 * 图层
	 */
	private Layer oLayer;

	/**
	 * 数据源
	 */
	private DataSource oDS;

	/**
	 * ShapeFile实体类
	 */
	private ShapeFileBean shpbean;

	static {
		// 注册
		ogr.RegisterAll();
		// 为了支持中文路径
		gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
	}

	public ShapeFileWriter(String filename, ShapeFileBean shpbean) {
		this.FileName = filename;
		this.shpbean = shpbean;
	}

	/**
	 * 创建ShapeFile
	 */
	public void create() {
		createDriver();
		createDataSource();
		createoLayer();
		if (oLayer!= null) {
			createallField();
			createFeature();
			save();
		}
	}

	/**
	 * 创建Driver
	 */
	private void createDriver() {
		oDriver = ogr.GetDriverByName(strDriverName);
		if (oDriver == null) {
			LogUtil.debug(FileName + " 驱动不可用!");
			return;
		}
	}

	/**
	 * 创建数据源
	 */
	private void createDataSource() {
		oDS = oDriver.CreateDataSource(FileName, null);
		if (oDS == null) {
			LogUtil.debug("创建矢量文件【" + FileName + "】失败!");
			return;
		}
	}

	/**
	 * 创建图层
	 */
	private void createoLayer() {
        Vector<String> options = new Vector<>();
        options.add("ENCODING=UTF-8");
		File file = new File(FileName);
		String name = file.getName();
		name = name.substring(0, name.lastIndexOf("."));
		oLayer = oDS.CreateLayer(name, shpbean.getSptref(), ogr.wkbPoint, options);
		if (oLayer == null) {
			LogUtil.debug("图层创建失败!");
			return;
		}
	}

	/**
	 * 从ShapeTitle类读取数据,批量创建字段
	 */
	private void createallField() {
		List<ShapeTitle> list = shpbean.getTitle();
		for (ShapeTitle title:list) {
			if((title.getLength()+"").isEmpty()) {
				createField(title.getName(),title.getType());
			}else if(!(title.getLength()+"").isEmpty()) {
				createField(title.getName(),title.getLength(),title.getType());
			}
		}
	}
	
	/**创建字段(不指定长度)
	 * @param name
	 * @param type
	 */
	private void createField(String name, int type) {
		FieldDefn oFieldID = new FieldDefn(name, type);
		oLayer.CreateField(oFieldID);
	}

	/**创建字段(指定长度)
	 * @param name
	 * @param length
	 * @param type
	 */
	private void createField(String name, int length, int type) {
		FieldDefn oFieldName = new FieldDefn(name, type);
		oFieldName.SetWidth(length);
		oLayer.CreateField(oFieldName);
	}

	/**
	 * 创建要素,要素包含属性与地理信息
	 */
	private void createFeature() {
		FeatureDefn oDefn = oLayer.GetLayerDefn();
		List<Map<Integer, Object>> feature = shpbean.getFeature();
		LogUtil.info(feature.size());
		for (Map<Integer, Object> data : feature) {
			Feature f = new Feature(oDefn);
			for (Entry<Integer, Object> entry : data.entrySet()) {
				if (entry.getKey() == -1) {
					f.SetGeometry((Geometry) entry.getValue());
				} else if (entry.getKey() > -1) {
					f.SetField(entry.getKey(), entry.getValue().toString());
				}
			}
			oLayer.CreateFeature(f);
		}
	}

	/**
	 * 保存数据
	 */
	private void save() {
		if (oDS != null) {
			oDS.SyncToDisk();
		}
	}
}

调用例子

读取Excel表格(含XY坐标)中的属性,生成点状矢量文件


import java.io.File;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.gdal.ogr.Geometry;
import org.gdal.ogr.ogr;
import org.gdal.osr.SpatialReference;

import com.hjzx.util.ExcelParser;
import com.hjzx.util.entity.ExcelBean;
import com.util.ShapeFileWriter;
import com.util.entity.ShapeFileBean;
import com.util.entity.ShapeTitle;

public class Excel2ShpConverter {

	public static void main(String[] args) {

		File file = new File(args[0]);
		File dstfile = new File(args[1]);
		if (!file.exists()) {
			System.out.println("源文件不存在");
			return;
		}

		ShapeFileBean shpbean = new ShapeFileBean();
		// 用wkt字符串设置投影
		String wktstr = 		"GEOGCS[\"GCS_WGS_1984\",DATUM[\"D_WGS_1984\",SPHEROID[\"WGS_1984\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"Degree\",0.0174532925199433]]";
		SpatialReference Sptref = new SpatialReference(wktstr);
		shpbean.setSptref(Sptref);
		// 设置字段
		List<ShapeTitle> titilelist = new ArrayList<>();
		ShapeTitle id = new ShapeTitle("id", ogr.OFTInteger64);
		ShapeTitle zh = new ShapeTitle("站号", 10, ogr.OFTString);
		titilelist.add(id);
		titilelist.add(zh);
		shpbean.setTitle(titilelist);
		
        // 从Excel表中读取属性及经纬度坐标为List
		List<Map<Integer, Object>> excelbean = GetDataExcelBean(file.getAbsolutePath());
        // 设置要素
		List<Map<Integer, Object>> features = new ArrayList<>();

		for (Map<Integer, Object> map : excelbean) {
			Map<Integer, Object> feature = new LinkedHashMap<>();
       // 用wkt字符串创建Geometry
			Geometry geo = Geometry.CreateFromWkt("POINT(" + map.get(4) + " " + map.get(5) + ")");
       // 将Geometry放到key=-1的位置
			feature.put(-1, geo);
			feature.put(0, map.get(1));
			feature.put(1, map.get(2));

			features.add(feature);
		}

		shpbean.setFeature(features);
		ShapeFileWriter shpw = new ShapeFileWriter(dstfile.getAbsolutePath() + file.getName() + ".shp", shpbean);
		shpw.create();
	}

	private static List<Map<Integer, Object>> GetDataExcelBean(String path) {
		ExcelParser expaser = new ExcelParser();
		expaser.Read(path, 2);
		ExcelBean exbean = expaser.GetExcelBean();
		List<Map<Integer, Object>> rows = exbean.getRow();
		return rows;
	}
}

以上代码中GetDataExcelBean是读取表格转换为List<Map<Integer, Object>>的方法,其实现细节与本文主要内容无关,不在这里赘述。

wkt字符串是描述几何对象的文本,其规范可以参考以下网址https://www.osgeo.cn/doc_ogcstd/ogc_standard/ch02_chapter1/chapter.html#wkt

由于水平有限,代码写得不算好,勉强能用。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要将Shapefile格式文件转换为DWG格式,你可以使用GDAL库中的OGR(OpenGIS Simple Features Reference Implementation)功能。下面是使用GDAL进行转换的基本步骤: 1. 引用GDAL和OGR库:在C#项目中,首先需要引用GDAL和OGR库。你可以在代码文件中添加以下引用: ```csharp using OSGeo.GDAL; using OSGeo.OGR; ``` 2. 初始化GDAL:在程序的入口点或初始化代码中,调用GDAL的初始化方法: ```csharp Gdal.AllRegister(); ``` 3. 打开Shapefile数据源:使用OGR打开Shapefile数据源: ```csharp DataSource sourceDS = Ogr.Open("path/to/your/shapefile", 0); ``` 4. 创建DWG文件数据源:使用OGR创建DWG文件数据源: ```csharp Driver dwgDriver = Ogr.GetDriverByName("DWG"); DataSource targetDS = dwgDriver.CreateDataSource("path/to/your/dwgfile", null); ``` 5. 复制图层:遍历Shapefile数据源中的图层,并将其复制到DWG数据源中: ```csharp for (int i = 0; i < sourceDS.GetLayerCount(); i++) { Layer sourceLayer = sourceDS.GetLayerByIndex(i); Layer targetLayer = targetDS.CreateLayer(sourceLayer.GetName(), sourceLayer.GetSpatialRef(), sourceLayer.GetGeomType(), null); FeatureDefn featureDefn = sourceLayer.GetLayerDefn(); for (int j = 0; j < featureDefn.GetFieldCount(); j++) { FieldDefn fieldDefn = featureDefn.GetFieldDefn(j); targetLayer.CreateField(fieldDefn, 1); } sourceLayer.ResetReading(); Feature feature; while ((feature = sourceLayer.GetNextFeature()) != null) { Feature targetFeature = new Feature(featureDefn); targetFeature.SetFrom(feature); targetLayer.CreateFeature(targetFeature); feature.Dispose(); targetFeature.Dispose(); } sourceLayer.Dispose(); targetLayer.Dispose(); } ``` 6. 关闭数据源:在使用完数据后,需要关闭数据源以释放资源: ```csharp sourceDS.Dispose(); targetDS.Dispose(); ``` 以上是使用GDAL库将Shapefile格式文件转换为DWG格式的基本步骤。请注意,转换过程中可能需要进行投影转换或其他额外的操作,具体取决于你的数据和需求。你可以根据需要进行进一步的处理和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值