目录
01注册驱动,设置环境变量
02 获取矢量图层
03创建矢量数据
04获取图层、字段、要素属性信息
05不同数据源读取要素属性时中文存在不同程度乱码,需要获取重新字符串信息
程序初始化时注册一次驱动和设置环境变量即可。
public static void InitinalGdal()
{
try
{
OSGeo.GDAL.Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");// 为了支持中文路径
//OSGeo.GDAL.Gdal.SetConfigOption("GDAL_DATA", "gdal-data");
OSGeo.GDAL.Gdal.SetConfigOption("SHAPE_ENCODING", ""); // 为了使属性表字段支持中文
OSGeo.GDAL.Gdal.AllRegister();
Ogr.RegisterAll();
}
catch (System.Exception ex)
{
}
}
///
/// 获取shp图层
///
/// shp路径
///
public static Layer GetSHPLayer(string shpPath)
{
Layer layer = null;
try
{
//InitinalGdal();
DataSource dsSHP = Ogr.Open(shpPath, 0);
layer = dsSHP.GetLayerByIndex(0);
string name = layer.GetName();
SpatialReference sr = layer.GetSpatialRef();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return layer;
}
///
/// 获取gdb数据
///
/// gdb路径
/// 图层名
///
public static Layer GetGDBLayer(string gdbPath, string tableName)
{
//InitinalGdal();
Layer layer = null;
try
{
//方法一
//String gdbDriverName = OpenFileGDB
//Driver gdbDriver = Ogr.GetDriverByName(gdbDriverName);
//if (gdbDriver == null)
//{
// string errInfo = gdbDriverName + " 驱动不可用!\n";
// //return false;
//}
//DataSource gdbDataSource;
获取gdb数据源
//gdbDataSource = gdbDriver.Open(gdbPath, 0);
//int layerCount = dsGDB.GetLayerCount();
//for (int i = 0; i < layerCount; i++)
//{
// layer = dsGDB.GetLayerByIndex(i);
//}
//方法二
DataSource dsGDB = Ogr.Open(gdbPath, 0);
layer = dsGDB.GetLayerByName(tableName);
string name = layer.GetName();
SpatialReference sr = layer.GetSpatialRef();
}
catch (Exception ex)
{
}
return layer;
}
///
/// 获取post数据库图层
///
/// 连接信息
/// 模式名
/// 图层名
///
public static Layer GetPostLayer(string connPost, string schema, string tableName)
{
//string connPost = string.Format("PG:dbname={0} host={1} port={2} user={3} password={4}", dbname,host, port, user, password);
//InitinalGdal();
Layer layer = null;
try
{
DataSource dsPost = Ogr.Open(connPost, 0);
layer = dsPost.GetLayerByName(schema + "." + tableName);
SpatialReference sr = layer.GetSpatialRef();
}
catch (Exception ex)
{
}
return layer;
}
public static void CreatSHP(string shpPath, string tableName)
{
try
{
//InitinalGdal();
Driver drv = Ogr.GetDriverByName("ESRI Shapefile");
DataSource ds = drv.CreateDataSource(shpPath, new string[] { });
//设置坐标系
SpatialReference sr = new SpatialReference("");
sr.ImportFromEPSG(4490);
//创建点图层
Layer layer = ds.CreateLayer(tableName, sr, wkbGeometryType.wkbPoint, new string[] { });
//创建字段
FieldDefn fdefn = new FieldDefn("Name", FieldType.OFTString);
fdefn.SetWidth(32);
if (layer.CreateField(fdefn, 1) != 0)
{
Console.WriteLine("创建字段失败");
System.Environment.Exit(-1);
}
fdefn = new FieldDefn("IntField", FieldType.OFTInteger);
if (layer.CreateField(fdefn, 1) != 0)
{
Console.WriteLine("创建字段失败");
System.Environment.Exit(-1);
}
fdefn = new FieldDefn("DubleField", FieldType.OFTReal);
if (layer.CreateField(fdefn, 1) != 0)
{
Console.WriteLine("创建字段失败");
System.Environment.Exit(-1);
}
fdefn = new FieldDefn("DateField", FieldType.OFTDate);
if (layer.CreateField(fdefn, 1) != 0)
{
Console.WriteLine("创建字段失败");
System.Environment.Exit(-1);
}
//创建要素
Feature feature = new Feature(layer.GetLayerDefn());
feature.SetField("Name", "value");
feature.SetField("IntField", (int)123);
feature.SetField("DubleField", (double)12.345);
feature.SetField("DateField", 2007, 3, 15, 18, 24, 30, 0);
//设置几何图形
//POLYGON((1 1,5 1,5 5,1 5,1 1),(2 2,2 3,3 3,3 2,2 2))
//MULTIPOLYGON(((1 1,5 1,5 5,1 5,1 1),(2 2,2 3,3 3,3 2,2 2)),((6 3,9 2,9 4,6 3)))
//LINESTRING(3 4,10 50,20 25)
//MULTILINESTRING((3 4,10 50,20 25),(-5 -8,-10 -8,-15 -4))
Geometry geom = Geometry.CreateFromWkt("POINT(47.0 19.2)");
if (feature.SetGeometry(geom) != 0)
{
Console.WriteLine("feature添加图形失败");
System.Environment.Exit(-1);
}
if (layer.CreateFeature(feature) != 0)
{
Console.WriteLine("shapefile创建要素失败");
System.Environment.Exit(-1);
}
feature.Dispose();
ds.Dispose();
drv.Dispose();
}
catch (System.Exception ex)
{
}
}
GDAL 2.0 对gdb和mdb的支持
创建gdb;GDAL对gdb文件只支持读取,不支持写入
依赖于ESRI FileGDBAPI我们可以实现对gdb数据的读取
下载编译好的gdal后可以在bin\gdal\plugins-external目录下找到ogr_FileGDB.dll,这是以插件形式将FileGDBAPI进行了整合编译。使gdal支持gdb数据读写需要以下几个步骤:
1、将该dll放置在与gdal20X.dll同级目录下新建的gdalplugins文件夹下
2、从https://github.com/Esri/file-geodatabase-api/tree/master/FileGDB_API_1.4下载得到对应该编译版本的FileGDBAPI.dll,放置在gdal20X.dll同级目录。
3、驱动名称由OpenFileGDB改为FileGDB
public static void CreatGDB(string gdbPath,Layer pgLayer )
{
//依据图层创建gdb
InitinalGdal();
string tableName = pgLayer.GetName();
//获取gdb驱动
String gdbDriverName = "FileGDB";//OpenFileGDB
Driver gdbDriver = Ogr.GetDriverByName(gdbDriverName);
if (gdbDriver == null)
{
Console.WriteLine("不支持" + gdbDriverName + "驱动");
return;
}
DataSource gdbDataSource = null;
if (!Directory.Exists(gdbPath))
gdbDataSource = gdbDriver.CreateDataSource(gdbPath, null);
else
gdbDataSource = gdbDriver.Open(gdbPath, 1);
//创建图层
Layer gdbLayer = gdbDataSource.CreateLayer(pgLayer.GetName(), pgLayer.GetSpatialRef(), pgLayer.GetGeomType(), null);
if (gdbLayer == null)
{
Console.WriteLine("GDB创建图层失败");
return;
}
//字段
List listField = new List();
FeatureDefn pgDefn = pgLayer.GetLayerDefn();
int iFieldCount = pgDefn.GetFieldCount();
for (int i = 0; i < iFieldCount; i++)
{
FieldDefn oField = pgDefn.GetFieldDefn(i);
string name = oField.GetName();
listField.Add(name);
int tt = gdbLayer.CreateField(oField, 1);
}
//数据记录
gdbDataSource.StartTransaction(1);
Feature oFeature = null;
Feature pFeature = null;
int iFecCount = Convert.ToInt32(pgLayer.GetFeatureCount(0));
int index = 0;
if (iFecCount == 0)
return;
while ((oFeature = pgLayer.GetNextFeature()) != null)
{
index++;
pFeature = new Feature(pgDefn);
pFeature.SetGeometry(oFeature.GetGeometryRef());
for (int iAttr = 0; iAttr < iFieldCount; iAttr++)
{
FieldDefn oField = pgDefn.GetFieldDefn(iAttr);
//string fieldName = oField.GetName();
string val = "";
try
{
val = oFeature.GetFieldAsString(iAttr);
if (!Regex.IsMatch(val, @"^[+-]?\d*[.]?\d*$"))//数字不处理
val = GetRightString.getRightStr(oFeature, iAttr, "GDB");//如果layer是根据SQL获取则 iAttr+1
}
catch (Exception)
{
continue;
}
string fieldTypr = oField.GetFieldType().ToString();
switch (fieldTypr)
{
case "OFTString":
case "OFTStringList":
case "OFTWideString":
case "OFTWideStringList":
case "OFTBinary":
case "OFTDate":
case "OFTDateTime":
case "OFTTime":
pFeature.SetField(iAttr, val); ;
break;
case "OFTInteger":
case "OFTIntegerList":
case "OFTInteger64":
case "OFTInteger64List":
int saveIntValue = 0;
if (int.TryParse(val, out saveIntValue))
{
pFeature.SetField(iAttr, saveIntValue);
}
break;
case "OFTReal":
case "OFTRealList":
double saveDoubleValue = 0;
if (double.TryParse(val, out saveDoubleValue))
{
pFeature.SetField(iAttr, saveDoubleValue);
}
break;
}
}
gdbLayer.CreateFeature(pFeature);
}
pFeature.Dispose();
gdbDataSource.CommitTransaction();
//写入文件
gdbLayer.SyncToDisk();
gdbDataSource.SyncToDisk();
gdbLayer.Dispose();
gdbDataSource.Dispose();
pgLayer.Dispose();
}
public static void ReportLayer(Layer layer)
{
FeatureDefn def = layer.GetLayerDefn();
Console.WriteLine("Layer name: " + def.GetName());
Console.WriteLine("Feature Count: " + layer.GetFeatureCount(1));
Envelope ext = new Envelope();
layer.GetExtent(ext, 1);
Console.WriteLine("Extent: " + ext.MinX + "," + ext.MaxX + "," +
ext.MinY + "," + ext.MaxY);
OSGeo.OSR.SpatialReference sr = layer.GetSpatialRef();
string srs_wkt;
if (sr != null)
{
sr.ExportToPrettyWkt(out srs_wkt, 1);
}
else
srs_wkt = "(unknown)";
Console.WriteLine("Layer SRS WKT: " + srs_wkt);
//获取字段信息
Console.WriteLine("Field definition:");
for (int iAttr = 0; iAttr < def.GetFieldCount(); iAttr++)
{
FieldDefn fdef = def.GetFieldDefn(iAttr);
Console.WriteLine(fdef.GetNameRef() + ": " +
fdef.GetFieldTypeName(fdef.GetFieldType()) + " (" +
fdef.GetWidth() + "." +
fdef.GetPrecision() + ")");
}
Feature feat;
while ((feat = layer.GetNextFeature()) != null)
{
ReportFeature(feat, def);
feat.Dispose();
}
}
public static void ReportFeature(Feature feat, FeatureDefn def)
{
//def = feat.GetDefnRef();
//def = layer.GetLayerDefn();
Console.WriteLine("Feature(" + def.GetName() + "): " + feat.GetFID());
for (int iField = 0; iField < feat.GetFieldCount(); iField++)
{
FieldDefn fdef = def.GetFieldDefn(iField);
Console.Write(fdef.GetNameRef() + " (" +
fdef.GetFieldTypeName(fdef.GetFieldType()) + ") = ");
if (feat.IsFieldSet(iField))
Console.WriteLine(feat.GetFieldAsString(iField));
else
Console.WriteLine("(null)");
}
if (feat.GetStyleString() != null)
Console.WriteLine(" Style = " + feat.GetStyleString());
Geometry geom = feat.GetGeometryRef();
if (geom != null)
Console.WriteLine(" " + geom.GetGeometryName() +
"(" + geom.GetGeometryType() + ")");
Envelope env = new Envelope();
geom.GetEnvelope(env);
Console.WriteLine(" ENVELOPE: " + env.MinX + "," + env.MaxX + "," +
env.MinY + "," + env.MaxY);
string geom_wkt;
geom.ExportToWkt(out geom_wkt);
Console.WriteLine(" " + geom_wkt);
}
///
/// 中文字段值特殊处理类
///
public static class GetRightString
{
[DllImport("gdal202.dll", EntryPoint = "OGR_F_GetFieldAsString", CallingConvention = CallingConvention.Cdecl)]
public extern static System.IntPtr OGR_F_GetFieldAsString(HandleRef handle, int i);
[DllImport("gdal202.dll", EntryPoint = "CPLStrnlen", CallingConvention = CallingConvention.Cdecl)]
public extern static uint CPLStrnlen(IntPtr handle, uint nMaxLen);
public static String getRightStr(Feature fe, int index, string workspaceType)
{
IntPtr pchar = OGR_F_GetFieldAsString(OSGeo.OGR.Feature.getCPtr(fe), index);
//if (workspaceType == "SHP" )非UTF8编码
//{
// String str = Marshal.PtrToStringAnsi(pchar);
// return str;
//}
if (workspaceType == "SHP")//UTF8编码
{
int length = (int)CPLStrnlen(pchar, uint.MaxValue);
byte[] strbuf = new byte[length];
Marshal.Copy(pchar, strbuf, 0, length);
string utf8String = System.Text.Encoding.UTF8.GetString(strbuf);
return utf8String;
}
else if (workspaceType == "GDB")
{
int length = (int)CPLStrnlen(pchar, uint.MaxValue);
byte[] strbuf = new byte[length];
Marshal.Copy(pchar, strbuf, 0, length);
string utf8String = System.Text.Encoding.UTF8.GetString(strbuf);
return utf8String;
}
else
{
return fe.GetFieldAsString(index);
}
}
[DllImport("gdal204.dll", EntryPoint = "OGR_F_SetFieldString", CallingConvention = CallingConvention.Cdecl)]
public extern static void OGR_F_SetFieldString(HandleRef handle, int index, string val);
public static void setFieldString(Feature fe, int index, string val, string workspaceType)
{
if (workspaceType == "SHP")
{
OGR_F_SetFieldString(OSGeo.OGR.Feature.getCPtr(fe), index, val);
}
else
{
fe.SetField(index, val);
}
}
}