C# gdal 将geojson批量导入到 gdb(FileGeodatabase)文件中

需求

需要将地块的geojson数据导入到gdb文件中

思路

为了方便后期使用和集成,于是采用C#(或者java)的方式,利用gdal创建gdb文件并将geojson数据导入其中

linux平台使用

环境

win10、VS2015

实现过程

1、文件准备

   gdal下载地址:https://www.gisinternals.com/archive.php

   我使用的版本:release-1900-x64-gdal-3-0-4-mapserver-7-4-3.zip

   下载gdal开发文件和创建gdb的驱动文件:

 

2、开发环境搭建

    借鉴:https://blog.csdn.net/xlp789/article/details/128363235

   1)、安装gdal-300-1900-x64-filegdb.msi文件,安装后找到对应文件夹,将文件复制到开发工程的bin\Debug目录中

 

2)、将release-1900-x64-gdal-3-0-4-mapserver-7-4-3\bin\gdal\csharp下的8个dll拷贝到开发工程的bin\Debug目录中

 3)、将release-1900-x64-gdal-3-0-4-mapserver-7-4-3\bin\下的文件拷贝到开发工程的bin\Debug目录中

 4)、设置工程的目标平台为X64,如下图所示:

 5)、添加引用 包含四个dll:gdal_csharp.dll、gdalconst_csharp.dll 、ogr_csharp.dll 、osr_csharp.dll ,如下图所示

 6)、设置环境变量

因为开发过程中涉及创建图层坐标系,需要使用proj.db,需要设置PROJ_LIB环境变量:D:\software\release-1900-x64-gdal-3-0-4-mapserver-7-4-3\bin\proj6\share,如下所示:

 7)、初始化gdal开发环境

   //为了支持中文路径
   Gdal.SetConfigOption("SHAPE_ENCODING", ""); //解决字段乱码问题
   Gdal.AllRegister();
   Ogr.RegisterAll();
   OSGeo.GDAL.Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");

 

8)、geojson数据检查方法1

 //json数据检查  特定格式
        public string GeoJsonCheck(string filepath)
        {
            try
            {
                System.IO.FileInfo fileInfo = fileInfo = new System.IO.FileInfo(filepath);
                double fileSize = System.Math.Ceiling(fileInfo.Length / 1024.0/1024);
                if (fileSize > 25) {
                    return "文件过大("+ fileSize + " MB),不能大于 25MB";
                }
                string json = string.Empty;
                using (FileStream fs = new FileStream(filepath, FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite, FileShare.ReadWrite))
                {
                    using (StreamReader sr = new StreamReader(fs, Encoding.UTF8))
                    {
                        json = sr.ReadToEnd().ToString();
                        JObject jo = (JObject)JsonConvert.DeserializeObject(json);
                        JArray features = (JArray)jo["features"];
                        for (int i = 0; i < features.Count; i++)
                        {
                            JObject fea = (JObject)features[i];
                            JArray coordinates = (JArray)fea["geometry"]["coordinates"];
                          
                            for (int a = 0; a < coordinates.Count; a++)
                            {
                                bool isError = false;
                                JArray ring1 = (JArray)coordinates[a];
                                for (int b = 0; b < ring1.Count; b++)
                                {
                                    if (isError) break;
                                    JArray ring2 = (JArray)ring1[b];
                                    for (int c = 0; c < ring2.Count; c++)
                                    {
                                        JArray ring3 = (JArray)ring2[c];
                                        if (ring3.Count > 2)
                                        {
                                            coordinates.RemoveAt(a);
                                            a--;
                                            isError = true;
                                            break;
                                        }
                                    }
                                }
                            }
                        }

                        // 将文件指针重置到开头
                        fs.Seek(0, SeekOrigin.Begin);
                        // 写入修改后的内容
                        byte[] modifiedBuffer = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(jo));
                        fs.Write(modifiedBuffer, 0, modifiedBuffer.Length);

                        // 如果新内容比原内容短,需要截断文件
                        fs.SetLength(modifiedBuffer.Length);
                    }
                }
                return "";
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

9)、geojson数据检查,方法2

        //json数据检查,使用geojson.dll
        public string GeoJsonCheck(string filepath)
        {
            string result = "";
            string json = string.Empty;
            using (FileStream fs = new FileStream(filepath, FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                using (StreamReader sr = new StreamReader(fs, Encoding.UTF8))
                {
                    try
                    {
                        json = sr.ReadToEnd().ToString();
                        GeoJson data = JsonConvert.DeserializeObject<GeoJson>(json);
                    }
                    catch (Exception ex)
                    {

                        result="格式错误";
                    }
                  
                
                }
            }
            return result;
        }

10、导入多个geojson文件到gdb文件中

 //导入多个geojson文件到gdb中
        public string importGeojsonsToGdb(List<string> inputGeojsonfiles, string gdbFilePath)
        {
            string result = "";
            try
            {
                // gdb文件存在就删除
                if (Directory.Exists(gdbFilePath))
                {
                    // 删除目录及其内容
                    Directory.Delete(gdbFilePath, true);
                }
                // 创建或打开GDB文件
                string driverName = "FileGDB";
                OSGeo.OGR.Driver gdbDriver = Ogr.GetDriverByName(driverName);
                if (gdbDriver == null)
                {
                    return "无法找到FileGDB驱动";
                    
                }
                DataSource gdbDataSource = gdbDriver.CreateDataSource(gdbFilePath, null);
                if (gdbDataSource == null)
                {
                    return "无法创建或打开GDB文件";
                }
                // 获取第一个输入图层的结构(作为输出图层的模板)
                DataSource firstInputDataSource = Ogr.Open(inputGeojsonfiles[0], 0);
                if (firstInputDataSource == null)
                {
                    result = "读取失败: " + inputGeojsonfiles[0];
                    return result;
                }
                Layer firstInputLayer = firstInputDataSource.GetLayerByIndex(0);
                if (firstInputLayer == null)
                {
                    result ="获取图层失败: " + inputGeojsonfiles[0];
                    return result;
                }

                // 合并所有输入 Shapefile 的要素
                foreach (string inputShapefile in inputGeojsonfiles)
                {
                    string fileName = Path.GetFileNameWithoutExtension(inputShapefile);
                    // 在GDB中创建相同的图层
                    Layer gdbLayer = gdbDataSource.CreateLayer(fileName, firstInputLayer.GetSpatialRef(), firstInputLayer.GetGeomType(), null);
                    if (gdbLayer == null)
                    {
                        return "无法在GDB中创建图层";
                    }

                    // 复制字段定义
                    FeatureDefn inputLayerDef = firstInputLayer.GetLayerDefn();
                    for (int i = 0; i < inputLayerDef.GetFieldCount(); i++)
                    {
                        FieldDefn fieldDef = inputLayerDef.GetFieldDefn(i);
                        if (gdbLayer.CreateField(fieldDef, 1) != Ogr.OGRERR_NONE)
                        {
                            result = "无法创建字段: " + fieldDef.GetName();
                            return result;
                        }
                    }
                    DataSource inputDataSource = Ogr.Open(inputShapefile, 0);
                    if (inputDataSource == null)
                    {
                        result="打开文件失败: " + inputShapefile;
                        return result;
                    }

                    Layer inputLayer = inputDataSource.GetLayerByIndex(0);
                    if (inputLayer == null)
                    {
                        result = "获取图层失败: " + inputShapefile;
                        return result;
                    }

                    // 复制要素
                    inputLayer.ResetReading();
                    OSGeo.OGR.Feature inputFeature;
                    while ((inputFeature = inputLayer.GetNextFeature()) != null)
                    {
                        OSGeo.OGR.Feature outputFeature = new OSGeo.OGR.Feature(gdbLayer.GetLayerDefn());
                        outputFeature.SetGeometry(inputFeature.GetGeometryRef());

                        // 复制字段值
                        for (int i = 0; i < inputLayerDef.GetFieldCount(); i++)
                        {
                            outputFeature.SetField(i, inputFeature.GetFieldAsString(i));
                        }

                        if (gdbLayer.CreateFeature(outputFeature) != Ogr.OGRERR_NONE)
                        {
                            return "复制要素到gdb失败";
                        }
                    }

                    // 释放输入数据源
                    inputDataSource.Dispose();
                }

                // 释放资源
                firstInputDataSource.Dispose();
                gdbDataSource.Dispose();
            }
            catch (Exception ex)
            {
                result = ex.Message;
            }
            return result;
        }

 

11、导入多个geojson并合并(坐标系、类型及属性字段相同)到gdb文件中

 //导入合并多个geojson文件到gdb中
        public string importGeojsonsAndMergeToGdb(List<string> inputGeojsonfiles, string gdbFilePath, string newLayerName)
        {
            string result = "";
            try
            {
                // gdb文件存在就删除
                if (Directory.Exists(gdbFilePath))
                {
                    // 删除目录及其内容
                    Directory.Delete(gdbFilePath, true);
                }
                // 创建或打开GDB文件
                string driverName = "FileGDB";
                OSGeo.OGR.Driver gdbDriver = Ogr.GetDriverByName(driverName);
                if (gdbDriver == null)
                {
                    return "无法找到FileGDB驱动";

                }
                DataSource gdbDataSource = gdbDriver.CreateDataSource(gdbFilePath, null);
                if (gdbDataSource == null)
                {
                    return "无法创建或打开GDB文件";
                }
                // 获取第一个输入图层的结构(作为输出图层的模板)
                DataSource firstInputDataSource = Ogr.Open(inputGeojsonfiles[0], 0);
                if (firstInputDataSource == null)
                {
                    result = "读取失败: " + inputGeojsonfiles[0];
                    return result;
                }
                Layer firstInputLayer = firstInputDataSource.GetLayerByIndex(0);
                if (firstInputLayer == null)
                {
                    result = "获取图层失败: " + inputGeojsonfiles[0];
                    return result;
                }
                // 在GDB中创建相同的图层
                Layer gdbLayer = gdbDataSource.CreateLayer(newLayerName, firstInputLayer.GetSpatialRef(), firstInputLayer.GetGeomType(), null);
                if (gdbLayer == null)
                {
                    return "无法在GDB中创建图层";
                }

                // 复制字段定义
                FeatureDefn inputLayerDef = firstInputLayer.GetLayerDefn();
                for (int i = 0; i < inputLayerDef.GetFieldCount(); i++)
                {
                    FieldDefn fieldDef = inputLayerDef.GetFieldDefn(i);
                    if (gdbLayer.CreateField(fieldDef, 1) != Ogr.OGRERR_NONE)
                    {
                        result = "无法创建字段: " + fieldDef.GetName();
                        return result;
                    }
                }

                // 合并所有输入 Shapefile 的要素
                foreach (string inputShapefile in inputGeojsonfiles)
                {

                    DataSource inputDataSource = Ogr.Open(inputShapefile, 0);
                    if (inputDataSource == null)
                    {
                        result = "打开文件失败: " + inputShapefile;
                        return result;
                    }

                    Layer inputLayer = inputDataSource.GetLayerByIndex(0);
                    if (inputLayer == null)
                    {
                        result = "获取图层失败: " + inputShapefile;
                        return result;
                    }

                    // 复制要素
                    inputLayer.ResetReading();
                    OSGeo.OGR.Feature inputFeature;
                    while ((inputFeature = inputLayer.GetNextFeature()) != null)
                    {
                        OSGeo.OGR.Feature outputFeature = new OSGeo.OGR.Feature(gdbLayer.GetLayerDefn());
                        outputFeature.SetGeometry(inputFeature.GetGeometryRef());

                        // 复制字段值
                        for (int i = 0; i < inputLayerDef.GetFieldCount(); i++)
                        {
                            outputFeature.SetField(i, inputFeature.GetFieldAsString(i));
                        }

                        if (gdbLayer.CreateFeature(outputFeature) != Ogr.OGRERR_NONE)
                        {
                            return "复制要素到gdb失败";
                        }
                    }

                    // 释放输入数据源
                    inputDataSource.Dispose();
                }

                // 释放资源
                firstInputDataSource.Dispose();
                gdbDataSource.Dispose();
            }
            catch (Exception ex)
            {
                result = ex.Message;
            }
            return result;
        }

12、界面截图如下:

 

posted on 2025-03-15 18:35  Geography爱好者  阅读(130)  评论(0)    收藏  举报

导航