shp文件與GeoJSON文件互轉


shp文件

shp文件全稱Shapefile文件,是美國環境系統研究所(ESRI)研制的GIS文件系統格式文件,是工業標准的矢量數據文件。

Shapefile將空間特征表中的非拓撲幾何對象和屬性信息存儲在數據集中,特征表中的幾何對象存為以坐標點集表示的圖形文件—SHP文件,Shapefile文件並不含拓撲(Topological)數據結構。一個Shape文件包括三個文件:一個主文件(.shp),一個索引文件(.shx),和一個dBASE(*.dbf)表。

在大多數GISer的日常工作中,得益於ArcGIS Desktop的廣泛使用,接觸最多的矢量數據恐怕就是shp文件了。

GeoJSON文件

GeoJSON歸根結底也是一種JSON,只不過它更適合記錄和描述各式各樣的地理數據結構。GeoJSON支持以下的實體類型:Point, LineString, Polygon, MultiPoint, MultiLineString, and MultiPolygon。此外,GeoJSON在 FeatureCollection 也包含了詳細的屬性信息。

需求背景

在我們實際的工作中,可能會涉及到GeoJSON和shp文件互轉的情況,因為這兩種文件格式都是非常流行的地理數據文件格式。

GeoJSON適合描述和傳輸地理數據,shp文件則適合用於分析和展示;

GeoJSON轉shp

以下代碼使用到了gdal依賴包,在Windows環境下如何配置gdal開發環境,大家可以看這篇文章GDAL,我暗戀你很久了!

在開始操作前,我們需要使用兩個網站,分別是:

該網站是又高德開放平台提供,是高德數據可視化項目旗下的非盈利性的工具網站,該網站可以非常便利的下載我國省市縣三級的GeoJSON數據。既可以下載為文件格式,也可以復制為文本格式。

相比於DataV,geojson.io網站的優勢在於可以支持用戶自主繪制圖形,以獲取目標區域的geojson。支持點、線、面、矩形來獲取目標區域的geojson,並支持一定的交互操作。

你可以選擇任何一個網站來獲取一個geojson來進行我們的代碼實戰操作。這里我選擇陝西省和內蒙古自治區的省界GeoJSON數據。

 package com.geovis.bin.utils.gis;
 
 import org.gdal.gdal.gdal;
 import org.gdal.ogr.DataSource;
 import org.gdal.ogr.ogr;
 
 import java.io.File;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.TimeZone;
 
 /**
  * @Author Wangb
  * @Date 2021/5/19 19:42.
  */
 public class GeojsonAndShpUtil {
     /**
      * Geojson 轉 shape
      *
      * @param sourcePath
      * @param destPath
      */
     public static void Geojson2Shape(String sourcePath, String destPath ) {
 
         Calendar instance = Calendar.getInstance(TimeZone.getTimeZone("GMT+08:00"));
         instance.setTime(new Date());
         String name = new File(sourcePath).getName();
         name = name.substring(0, name.lastIndexOf(".")) + ".shp";
 
         destPath += File.separator + instance.get(Calendar.YEAR) + (instance.get(Calendar.MONTH) + 1+ instance.get(Calendar.DATE) + instance.get(Calendar.HOUR) + instance.get(Calendar.MINUTE) + instance.get(Calendar.SECOND) + File.separator + name;
         File file1 = new File(destPath);
         if (!file1.exists()) {
             new File(file1.getParent()).mkdir();
        }
 
         // 注冊所有的驅動
         ogr.RegisterAll();
         // 為了支持中文路徑,請添加下面這句代碼
         gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
         // 為了使屬性表字段支持中文,請添加下面這句
         gdal.SetConfigOption("SHAPE_ENCODING", "");
         String strVectorFile = sourcePath;
         //打開數據
         DataSource ds = ogr.Open(strVectorFile, 0);
         if (ds == null) {
             System.out.println("打開文件失敗!");
             return;
        }
         System.out.println("打開文件成功!");
         // GeoJSON shp轉json的驅動
         // 面的記錄 ESRI Shapefile
         // 線的記錄 ESRI Shapefile
         // 點的記錄 ESRI Shapefile
         String strDriverName = "ESRI Shapefile";
         org.gdal.ogr.Driver dv = ogr.GetDriverByName(strDriverName);
         if (dv == null) {
             System.out.println("打開驅動失敗!");
             return;
        }
         System.out.println("打開驅動成功!");
         dv.CopyDataSource(ds, destPath);
         System.out.println("轉換成功!");
         ds.delete();
         dv.delete();
 
    }
 
     public static void main(String[] args) {
         Geojson2Shape("D:\\data\\陝西省.json", "D:\\data");
         Geojson2Shape("D:\\data\\內蒙古.json", "D:\\data");
    }
 
 }
 

 

使用上面的代碼進行轉換之后,就會在我們指定的D盤data文件夾下自動生成包含年月日時分秒的文件夾,該文件夾里就存放了我們轉換后的shp文件。

 

 

現在我們把生成的shp文件拖入ArcGIS內看一看

 

 

我們看到陝西省和內蒙古自治區的邊界貼合的很自然,右擊選擇Data Frame Properties,我們可以在Coordinate System里面看到當前shp文件的坐標系統是WGS84坐標系。

 

 

shp轉GeoJSON

接下來我們把shp文件轉為geoJSON試一下

 package com.geovis.bin.utils.gis;
 
 import org.gdal.gdal.gdal;
 import org.gdal.ogr.DataSource;
 import org.gdal.ogr.ogr;
 
 import java.io.File;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.TimeZone;
 
 /**
  * @Author Wangb
  * @Date 2021/5/19 19:42.
  */
 public class GeojsonAndShpUtil {
     /**
      * shape 轉 geojson
      *
      * @param sourcePath
      * @param destPath
      */
     public static void Shape2Geojson(String sourcePath, String destPath ) {
 
         Calendar instance = Calendar.getInstance(TimeZone.getTimeZone("GMT+08:00"));
         instance.setTime(new Date());
         String name = new File(sourcePath).getName();
         name = name.substring(0, name.lastIndexOf(".")) + ".json";
 
         destPath += File.separator + instance.get(Calendar.YEAR) + (instance.get(Calendar.MONTH) + 1) + instance.get(Calendar.DATE) + instance.get(Calendar.HOUR) + instance.get(Calendar.MINUTE) + instance.get(Calendar.SECOND) + File.separator + name;
         File file1 = new File(destPath);
         if (!file1.exists()) {
             new File(file1.getParent()).mkdir();
        }
 
         // 注冊所有的驅動
         ogr.RegisterAll();
         // 為了支持中文路徑,請添加下面這句代碼
         gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
         // 為了使屬性表字段支持中文,請添加下面這句
         gdal.SetConfigOption("SHAPE_ENCODING", "");
         String strVectorFile = sourcePath;
         //打開數據
         DataSource ds = ogr.Open(strVectorFile, 0);
         if (ds == null) {
             System.out.println("打開文件失敗!");
             return;
        }
         System.out.println("打開文件成功!");
         // GeoJSON shp轉json的驅動
         org.gdal.ogr.Driver dv = ogr.GetDriverByName("GeoJSON");
         if (dv == null) {
             System.out.println("打開驅動失敗!");
             return;
        }
         System.out.println("打開驅動成功!");
         dv.CopyDataSource(ds, destPath);
         System.out.println("轉換成功!");
         ds.delete();
         dv.delete();
    }
 
 
     public static void main(String[] args) {
         Shape2Geojson("D:\\data\\202111143545\\內蒙古.shp","D:\\data\\test");
    }
 
 }
 

轉換結果如下:

 

 

現在我們再Vscode里面對照一下,我們最初下載的內蒙古.geojson和反向生成的是否一樣。

 

 

通過仔細對比這個兩個文件,我們發現我們生成的內蒙古.geojson文件和之前下載的是完全一樣的,這種雙向驗證的方式在有些時候會非常有用。

好啦!今天的shp文件和GeoJSON文件的互轉就是以上的內容,希望可以幫助到你~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM