shp与geojson互转

5 篇文章 2 订阅
1 篇文章 0 订阅
       前言:最近我们项目有个需求,就是将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压缩包, 地址
shp与geojson互转

shp与geojson互转

shp与geojson互转
        
       2.解压,找到bin\gdal\apps
shp与geojson互转
 
       现在就可以开始转换了:
以管理员身份打开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工具,太令人吃惊了!!!
shp与geojson互转
 
-----------------------------------------------------------------------------------------------------------------
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;
            }
        }
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
shpgeojson工具是一种用于将Shapefile(shp)文件格式换为GeoJSON文件格式的软件工具。Shp文件是一种二进制矢量地理数据存储格式,常用于地理信息系统(GIS)中存储图形数据。而GeoJSON是一种开放的地理数据格式,用于表示地理空间对象的几何形状和属性信息。 使用shpgeojson工具可以提供以下几个主要功能: 1. 文件格式换:shpgeojson工具能够将shp文件换为对应的GeoJSON文件格式,使得用户可以在不同的GIS软件或平台上使用GeoJSON格式进行地理数据的分析和可视化。 2. 数据类型换:shpgeojson工具可以将shp文件中的点、线、面等不同类型的几何要素换为相应的GeoJSON几何对象类型,以方便进行后续的地理分析。 3. 属性数据保留:shpgeojson工具可以将shp文件中的属性数据(如名称、人口等信息)与换后的GeoJSON文件关联起来,并保留在生成的GeoJSON文件中,以提供更全面的地理信息。 4. 参数设置:shpgeojson工具通常提供一些可配置的参数选项,如坐标系换、属性字段映射等,以满足用户对换结果的特定需求。 总之,shpgeojson工具是一个非常有用的GIS数据处理工具,可以帮助用户方便地将shp文件换为广泛使用的GeoJSON格式,并进行进一步的地理数据分析和可视化。它为各类GIS应用提供了数据交的便利性和灵活性,同时也提高了数据的共享和可访问性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AIGIS.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值