前言:最近我们项目有个需求,就是将shp文件转为geojson。网上有很多的网站可以进行shp与geojson互转,但是这种做法并不能集成到我们系统中来,只适合单次调用。于是折腾了好多种办法,终于出来了,这里记录一下。

由于我们的项目采用的架构是Postgresql+Geoserver+OpenLayers+Asp.Net Core MVC,所以我们最初的使用方法是将shp导入postgresql,这样我们就可以调用了。并且postgresql也提供了一个工具叫做,shp2pgsql,专门用来导入shp文件的,于是我们就试了一下。
shp2pgsql的这个工具的使用cmd命令如下:
shp2pgsql -s 3857 -a -W "utf-8" -k -g "Shape"  D:\shp\test.shp "YZL"."YZL_ZLXB_PY" | psql -a test123  postgres
由于网上有很多的文章介绍这个工具怎么使用,我们在这里就不详细介绍了。上面给出的cmd命令并没有输入密码,那是因为我们在postgresql的配置文件中已经写好了,这里同样不再介绍,只给出shp2pgsql工具的常用命令:
OPTIONS:
●-s
设置srid,缺省为-1
●(-d|a|c|p)互斥选项:
-d  重新建立表,并插入数据。
-a  在同一个表中增加数据
-c  建立新表,并插入数据。(缺省)
-p  只创建表
●-g 指定要创建的表的空间字段名称(在追加数据时有用)
●-D  使用dump方式,缺省是生成sql
●-G  Use geography type (requires lon/lat data).
●-k  保持PostgreSQL标识符方式
●-i  使用int4类型dbf文件里的integer类型
●-I  在空间字段上建立索引
●-S  Generate simple geometries instead of MULTI geometries.
●-W shape文件属性列的字符格式。缺省是ascII
●-N 指定geometries为空时的操作(insert,skip,abort)
●-n  只导入dbf文件
●-?  显示帮助

上面我们的命令指定的空间字段是“Shape”,shp2pgsql识别出来的sql语句是:
insert into test123."YZL"."YZL_ZLXB_PY"("字段1","字段2",Shape) values("value1","value2","ShapeValue")
执行的时候总是报错,这就奇怪了,仔细看上面的sql语句,Shape是没有加引号的,所以一直报错,加上引号就好了。另外在网上查询资料的得到的结果是shp2pgsql是不识别大写的空间字段的,所以我加了一个测试的小写字段,居然真的成功了,这工具就是这么奇葩。。。。。
由于我们的表已经建好了,是不允许随便乱加字段的,所以回过头来继续说我们的解决方案。所幸shp2pgsql这个工具是可以生成sql文件的,里面的内容就是一条条insert语句。它的命令是这样的:
shp2pgsql -s 3857 -a -W "utf-8" -k -g "Shape"  D:\shp\test.shp "YZL"."YZL_ZLXB_PY" >d:\test.sql
这样,生成了test.sql文件,我们就可以用程序读取这个文件,把每一条sql语句都更改了,即给加上Shape加上引号。于是,将shp文件导入数据库的问题就成功解决了。
至此,关于postgresql的相关操作就结束了
-----------------------------------------------------------------------------
上面我们虽然成功的解决了将shp导入postgresql,但是我们只能导入特定的表,也就是说我们的shp文件表格式必须和我们数据库里的表结构一毛一样,这时非常操蛋的,于是我们就转向了鼎鼎大名的数据转换工具GDAL。
于是,我们本着内事不决问百度,外事不决问谷歌的原则,打开了谷歌浏览器,一搜,果然在Stack Overflow上找到了解决方案,代码也不复杂,于是我们在Nuget服务器上找到了GDAL .Net Core的包,引用dll,开始上代码:
C# Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/// 
        /// 将shp转为geojson
        /// 
        /// shp文件全路径
        /// 
        public static List<</span>object> ConvertShp2Geojson(string shapeFilePath)
        {
            try
            {
                // 为了支持中文路径  
                Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
                // 为了使属性表字段支持中文  
                Gdal.SetConfigOption("SHAPE_ENCODING", "");
                Gdal.AllRegister();
                Ogr.RegisterAll();
                Driver drv = Ogr.GetDriverByName("ESRI Shapefile");
                var ds = drv.Open(shapeFilePath, 0);
                Layer layer = ds.GetLayerByIndex(0);
                Feature f;
                layer.ResetReading();
                List<</span>object> sb = new List<</span>object>();
                while ((f = layer.GetNextFeature()) != null)
                {
                    var geom = f.GetGeometryRef();
                    if (geom != null)
                    {
                        var geometryJson = geom.ExportToJson(new string[] { });
                        var obj = JsonConvert.DeserializeObject(geometryJson);
                        sb.Add(obj);
                    }
                }
                return sb;
            }
            catch (Exception e)
            {
                throw e;
            }
        }
高高兴兴的发布网站,本地测试,能跑!!!来吧,部署远程服务器,测试,报错The type initializer for 'OSGeo.OGR.OgrPINVOKE' threw an exception.
有没有搞错!!!本地可以跑,为什么服务器不能跑,本地是win10系统,服务器是windows Server2008,难道环境不一样?于是我们就开始给服务器安装环境,GDAL是C++开发出来,我们装C++2005,不行!C++2008,还不行!!,C++2010,还不行!!!这就尴尬了,算了,环境问题太难搞,此路不通,我们就换思路。
还是本着内事不决问百度,外事不决问谷歌的原则,我们打开了谷歌,一搜,原来GDAL也提供了一个工具,叫做ogr2ogr,就是做shp与geojson互转的。那么我们先来下这个工具,在GDAL的官网找了半天,没找到!!!这不应该啊。好吧,外面找不到,我们就回CSDN来找,一搜,果然有,居然要50个积分,你咋不去抢呢。还是忍痛弄了下来,打开压缩包一看,tmd,居然没有这个工具,你个死骗子。差评加曝光。
不到黄河不死心,再次上GDAL官网,还是没找上,算了,下载一个它的包吧,也许在那里面,下载下来一搜,还真有!!!哈哈哈,皇天不负有心人呀。贴上下载方式:
1.在GISinternal下载zip压缩包,地址

2.解压,找到bin\gdal\apps

 
现在就可以开始转换了:
以管理员身份打开cmd窗口,进入这个路径:
cd  D:\迅雷下载\release\bin\gdal\apps
1、shp转geojson命令:
ogr2ogr -f "GeoJSON"  C:\goal.json  C:\source.shp
其中goal.json文件会由这个工具自己创建
2、geojson转shp命令:
ogr2ogr -f "ESRI Shapefile"  C:\goal.shp  C:\source.json 
其中goal.shp文件也会由这个工具自己创建
知道了这些个命令,我们在程序里调用它就很容易了,不废话,直接上代码:
C# Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/// 
/// 调用ogr2ogr.exe将shp转为geojson
/// 
/// shp文件路径
public static string RunJsonConvertProcess(string shpfile)
{
    try
    {
        string dataDir = Directory.GetCurrentDirectory();
        string accessPath = dataDir + @"\bin\gdal\apps";
        string fileName = Path.GetFileNameWithoutExtension(shpfile);
        var jsonPath = shpfile.Substring(0, shpfile.LastIndexOf("\") + 1) + fileName + ".json";
        if (!File.Exists(accessPath + "\\ogr2ogr.exe"))
            throw new Exception("不存在转换工具ogr2ogr");
        string cmd = $"ogr2ogr -f "GeoJSON\" {jsonPath} {shpfile}";
        string str = string.Format(@"C:&cd {0}&{1}&{2}", accessPath, cmd,"exit");
        RunCmd(str);
        if(File.Exists(jsonPath))
            return jsonPath;
        else
            return "";
    }
    catch (Exception e)
    {
        return "error:"+e.Message;
    }

}
/// 
/// 执行cmd命令
/// 多命令请使用批处理命令连接符:
/// 
/// &:同时执行多个命令
/// |:将上一个命令的输出,作为下一个命令的输入
/// &&:当&&前的命令成功时,才执行&&后的命令
/// ||:当||前的命令失败时,才执行||后的命令
/// 
/// 
public static void RunCmd(string cmd)
{
    cmd = cmd.Trim().TrimEnd('&') + "&exit";//说明:不管命令是否成功均执行exit命令,否则当调用ReadToEnd()方法时,会处于假死状态
    using (Process p = new Process())
    {
        Console.InputEncoding = Encoding.UTF8;
        p.StartInfo.FileName = @"C:\Windows\System32\cmd.exe";
        p.StartInfo.UseShellExecute = false;        //是否使用操作系统shell启动
        p.StartInfo.RedirectStandardInput = true;   //接受来自调用程序的输入信息
        p.StartInfo.RedirectStandardOutput = true;  //由调用程序获取输出信息
        p.StartInfo.RedirectStandardError = true;   //重定向标准错误输出
        p.StartInfo.CreateNoWindow = true;          //不显示程序窗口
        p.Start();//启动程序

//向cmd窗口写入命令
        p.StandardInput.WriteLine(cmd);
        p.StandardInput.AutoFlush = true;

//获取cmd窗口的输出信息
        //output = p.StandardOutput.ReadToEnd();
        p.WaitForExit();//等待程序执行完退出进程
        p.Close();
    }
}

总结:shp2pgsql工具只能向某张特定的表导入数据,灵活性太差。ogr2ogr可以转换任意shp为geojson,非常灵活,我们当然选择后者。周五了,解决了一个大问题,可以愉快地过周末了,本次教程就分享到这里,我们下次再会。
------------------------------------------------------------------------------
2019.4.24更新:我在postgresql的安装目录中的bin文件夹中也找到ogr2ogr工具,太令人吃惊了!!!

 
-----------------------------------------------------------------------------------------------------------------
2019.4.26更新:之前代码好好的运行,最近不知道怎么突然不能用了,报错'ogr2ogr ' is not recognized as an internal or external command, operable program or batch file.折腾了好久才发现是环境变量的问题,但是我们已经设置了环境变量了啊,但是程序不认,于是我们只好在程序里设置下环境变量。
废话不多说,我们直接上代码,这次的代码包括三个方法,因为之前的函数名命名并不好,所以我们这次重新命名一下:
1、Shp2GeoJsonByGDAL     使用GDAL将shp转为geojson
2、Shp2GeoJsonByOgr        调用ogr2ogr.exe将shp转为geojson
3、Shp2PostgreSql              调用shp2pgsql工具生成sql文件
4、RunCmd                          执行cmd命令
C# Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/// 
        /// 使用GDAL将shp转为geojson
        /// 
        /// shp文件全路径
        /// 
        public static List<</span>object> Shp2GeoJsonByGDAL(string shapeFilePath)
        {
            try
            {
                // 为了支持中文路径  
                Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
                // 为了使属性表字段支持中文  
                Gdal.SetConfigOption("SHAPE_ENCODING", "");
                Gdal.AllRegister();
                Ogr.RegisterAll();
                Driver drv = Ogr.GetDriverByName("ESRI Shapefile");
                var ds = drv.Open(shapeFilePath, 0);
                Layer layer = ds.GetLayerByIndex(0);
                Feature f;
                layer.ResetReading();
                List<</span>object> sb = new List<</span>object>();
                while ((f = layer.GetNextFeature()) != null)
                {
                    var geom = f.GetGeometryRef();
                    if (geom != null)
                    {
                        var geometryJson = geom.ExportToJson(new string[] { });
                        var obj = JsonConvert.DeserializeObject(geometryJson);
                        sb.Add(obj);
                    }
                }
                return sb;
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        /// 
        /// 调用ogr2ogr.exe将shp转为geojson
        /// 
        /// shp文件路径
        public static string Shp2GeoJsonByOgr(string shpfile)
        {
            try
            {
                string dataDir = Directory.GetCurrentDirectory();
                string accessPath = dataDir + @"\bin\postgresql";
                string fileName = Path.GetFileNameWithoutExtension(shpfile);
                var jsonPath = shpfile.Substring(0, shpfile.LastIndexOf("\") + 1) + fileName + ".json";
                if (!File.Exists(accessPath + "\\ogr2ogr.exe"))
                    throw new Exception("不存在转换工具ogr2ogr");
                string cmd = $"ogr2ogr -f "GeoJSON\" {jsonPath} {shpfile}";
                string str = string.Format(@"C:&cd {0}&{1}&{2}", accessPath, cmd,"exit");

RunCmd(accessPath,str);

if(File.Exists(jsonPath))
                    return jsonPath;
                else
                    return "";
            }
            catch (Exception e)
            {
                return "error:"+e.Message;
            }

}
        /// 
        /// 执行cmd命令
        /// 多命令请使用批处理命令连接符:
        /// 
        /// &:同时执行多个命令
        /// |:将上一个命令的输出,作为下一个命令的输入
        /// &&:当&&前的命令成功时,才执行&&后的命令
        /// ||:当||前的命令失败时,才执行||后的命令
        /// 
        /// 要设置的环境变量
        /// 要执行的cmd命令
        public static string RunCmd(string environmentVariable, string cmd)
        {
            cmd = cmd.Trim().TrimEnd('&') + "&exit";//说明:不管命令是否成功均执行exit命令,否则当调用ReadToEnd()方法时,会处于假死状态
            string res = "";
            using (Process p = new Process())
            {

//先设置环境变量,再运行
                string path = Environment.GetEnvironmentVariable("path");
                Environment.SetEnvironmentVariable("path", path + environmentVariable + ";");

//.NET Core不支持gbk和gb2312,这里需要处理一下
                Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
                Console.InputEncoding = Encoding.UTF8;
                p.StartInfo.FileName = @"C:\Windows\System32\cmd.exe";
                p.StartInfo.UseShellExecute = false;        //是否使用操作系统shell启动
                p.StartInfo.RedirectStandardInput = true;   //接受来自调用程序的输入信息
                p.StartInfo.RedirectStandardOutput = true;  //由调用程序获取输出信息
                p.StartInfo.RedirectStandardError = true;   //重定向标准错误输出
                p.StartInfo.CreateNoWindow = true;          //不显示程序窗口
                p.Start();//启动程序

//向cmd窗口写入命令
                p.StandardInput.WriteLine(cmd);
                p.StandardInput.AutoFlush = true;
                p.WaitForExit();//等待程序执行完退出进程

//获取cmd窗口的输出信息
                string s = p.StandardOutput.ReadToEnd();
                //获取错误信息
                string error = p.StandardError.ReadToEnd();
                byte[] bytes = Encoding.GetEncoding("GB2312").GetBytes(s);
                res = Encoding.UTF8.GetString(bytes);
                
                p.Close();
            }
            return res;
        }
        /// 
        /// 调用shp2pgsql工具生成sql文件
        /// 
        /// 
        public static string Shp2PostgreSql(string shpfile)
        {
            try
            {
                string dataDir = Directory.GetCurrentDirectory();
                string accessPath = dataDir + @"\bin\postgresql";
                string fileName = Path.GetFileNameWithoutExtension(shpfile);
                var sqlPath = shpfile.Substring(0, shpfile.LastIndexOf("\") + 1) + fileName + ".sql";
                if (!File.Exists(accessPath + "\\shp2pgsql.exe"))
                    throw new Exception("不存在转换工具shp2pgsql");
                string cmd = $"shp2pgsql -s 3857 -a -W "gbk\" -k -g "Shape\"  {shpfile} "YZL\"."LDBG_QHTB_PY\" >{sqlPath}";
                string str = string.Format(@"C:&cd {0}&{1}&{2}", accessPath, cmd, "exit");
                RunCmd(accessPath, str);
                if (File.Exists(sqlPath))
                    return sqlPath;
                else
                    return "";
            }
            catch (Exception e)
            {
                return "error:" + e.Message;
            }
        }

shp与geojson互转相关推荐

  1. java 使用gdal_java-gdal实现shp转geojson

    安装gdal的话,将shp转geojson会非常简单.本文因项目需要,以java-gdal讲述如何实现.ps:当然只要装有gdal就都可以实现功能. ogr2ogr命令 在控制台执行如下语句: D:\ ...

  2. shp与json互转(转载)

    转自:http://blog.sina.com.cn/s/blog_673c98be0102v78i.html 对于搞GIS开发的,这2种数据格式太重要了. 一.shp转json 这个要容易些,方法也 ...

  3. Mars3D(含Cesium)数据及服务篇:shp转geojson格式

    shp格式介绍 Shapefile文件是ESRI公司ArcGIS平台的常用格式文件,是工业标准的矢量数据文件. Shapefile将空间特征表中的非拓扑几何对象和属性信息存储在数据集中,特征表中的几何 ...

  4. java使用geotools shp转geojson(wtk转geojson) 精度丢失

    java 使用geotools将shp转为geojson时,发现geojson的精度丢失,所以导致geojson展示在地图上如下图:(使用wkt转geojson也存在同样问题) 查看api发现是Geo ...

  5. arcgis更改图层坐标系_【干货】ArcGIS之shp文件坐标系互转

    原标题:[干货]ArcGIS之shp文件坐标系互转 准备arcgis10.4 shp文件,没有定义坐标系,格式是经纬度的 准备的数据如下: 1.先将shp文件定义为EPSG:4326 首先打开arct ...

  6. 用shp制作geoJson格式地图数据(shp convert to geoJson)

    本文紧接前文,简单说明利用shp数据制作Echarts支持的geoJson格式的地图数据.本文以北京市通州区各镇的shp数据为例进行说明. 今天是香港回归20周年之际,在这个特殊的日子,祝愿祖国繁荣昌 ...

  7. GeoTools——shp转geojson

    目录 一.引言 二.代码操作 1.服务端 2.返回数据 三.总结 一.引言 数据库中经常存储的格式是符合OGC标准的WKT或WKB,而在网络中经常传输的格式是json,因此我们会经常把各种数据转为ge ...

  8. Cesium加载建筑物模型(shp转Geojson\3Dtiles)

    本文主要介绍cesium加载Geojson和3dtile格式的建筑物模型文件,除此之外还介绍了Cesium工具栏的屏蔽方法.天地图的加载.地球初始状态设置等几个部分的内容,其中又不乏参照.优化诸如:  ...

  9. [Python] GDAL/OGR操作矢量数据(shp、GeoJSON)

    GDAL项目旨于地理数据抽象模型对地理数据文件进行读写管理:而其项目下有两大类模块:GDAL和OGR OGR提供操作矢量数据的API,GDAL模块提供栅格数据的API [相关链接] 1.GDAL/OG ...

最新文章

  1. 获取系统昨日最高峰时的AWR报告,get_hight_load_awr
  2. Php 链式执行,PHP实现链式操作的三种方法详解
  3. kettle、Oozie、camus、gobblin
  4. 合并K个排序链表—leetcode23
  5. 2007上半年網絡工程師考題
  6. JQuery + jquery插件
  7. java读取与写入excel(.xls .xlsx)
  8. BeanFactory容器的设计原理
  9. STL中容器的介绍及分类
  10. Excel函数公式大全—MATCH函数
  11. 数据库系统概念(中文版)(第6版)pdf
  12. 【历史上的今天】3 月 31 日:世界备份日;皮克斯创始人出生;《黑客帝国》上映
  13. 如何判断一个文件是否是jpeg格式?
  14. 2011计算机一级a,计算机一级A2011 上海.doc
  15. 使用Contect.Handler显示提交过来的“编辑成功”的信息
  16. matlab的shading,matlab colormap,caxis,shading,hsv,pcolor, alpha
  17. 布尔逻辑析取范式思考
  18. 罗技g502鼠标宏设置教程分享
  19. 基于MATLAB的线性规划解决方法——单纯形法
  20. word转换成excel导致身份证错乱的解决办法

热门文章

  1. string数据库使用和实践第一部分string数据库介绍
  2. windows下安装weblogic11g集群 BEA-149509报错
  3. C++:在查找预编译头时遇到意外的文件结尾。是否忘记了向源中添加 “#include “stdafx.h“”?
  4. 财务管理专业写毕业论文有没有什么好的选题?
  5. Linux find 实战
  6. QT 多目录多工程 配置
  7. 词典软件测试工资,必应词典客户端软件测试报告
  8. 【单片机基础篇】rc延迟电路
  9. jsp/servlet过滤器和struts2拦截器的有什么区别
  10. maven的settings配置文件详解