利用geotools实现Shapefile和GeoJSON相互转换

1、什么是GeoJSON

关于什么是GeoJSON,百度百科给出这样的定义:GeoJSON是一种对各种地理数据结构进行编码的格式,基于Javascript对象表示法的地理空间信息数据交换格式。

GeoJSON支持以下几何类型:点、线、面、多点、多线和多面。GeoJSON是一个包含属性特征的几何对象。

GeoJSON****规范****(RFC 7946)

2015年,互联网工程工作组(IETF)与最初的规范作者一起,形成了一个GeoJSON WG来标准化GeoJSON。RFC 7946于2016年8月发布,是GeoJSON格式的新标准规范,取代了2008年的GeoJSON规范。

有一个GeoJSON在线生成的网站,在地图上绘制图形,自动生成GeoJSON文件,可以与GeoJSON规范对照学习GeoJSON的格式。网址为:http://geojson.io

2、为什么进行相互转换

为何要对Shapefile和geojson格式两种文件进行相互转换?个人认为有两点原因:

(1)传统的Shapefile文件存储需要结合arcsde等数据库引擎,且数据量庞大,无法满足空间大数据的发展需求。将Shapefile转换成转换成geojson采用hadoop等大数据框架、hbase等文件数据库进行分布式存储读取管理是一种有效的解决方式。

(2)ArcGIS Server等商用软件为WebGIS的开发带来了极大的便利,但是商用软件昂贵的价格以及其对部署性能的高要求使得WebGIS的开发困难重重。GeoJSON是基于JSON格式的文件,能够与javascript完美结合,实现前端可视化展示,再利用geotools等开源技术可实现各种空间分析。

3、转换方式

基于java语言,采用geotools代码库进行Shapefile和geojson进行格式转换。其关键代码如下:

package com.geotools.convent;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.Reader;
import java.io.Serializable;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.geotools.data.FeatureWriter;
import org.geotools.data.Transaction;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geojson.feature.FeatureJSON;
import org.geotools.geojson.geom.GeometryJSON;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;

import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.MultiPoint;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

public class shpTogeojson {
    /**
     * geojson转换为shp文件
     * 
     * @param jsonPath
     * @param shpPath
     * @return
     */
    public Map geojson2Shape(String jsonPath, String shpPath) {
        Map map = new HashMap();
        GeometryJSON gjson = new GeometryJSON();
        try {
            // 读文件到Stringbuffer
            StringBuffer sb = new StringBuffer();
            BufferedReader br = null;
            try {
                br = new BufferedReader(new FileReader(jsonPath));
                String str;
                while ((str = br.readLine()) != null) {// 逐行读取
                    sb.append(str + "\r\n");
                }
                br.close();
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }

            JSONObject json = JSONObject.fromObject(sb.toString());
            JSONArray features = (JSONArray) json.get("features");
            JSONObject feature0 = JSONObject.fromObject(features.get(0).toString());
            // 获取属性名称
            Set properties = JSONObject.fromObject(feature0.get("properties")).keySet();
            String strType = ((JSONObject) feature0.get("geometry")).getString("type").toString();

            Class<?> geoType = null;
            switch (strType) {
            case "Point":
                geoType = Point.class;
                break;
            case "MultiPoint":
                geoType = MultiPoint.class;
                break;
            case "LineString":
                geoType = LineString.class;
                break;
            case "MultiLineString":
                geoType = MultiLineString.class;
                break;
            case "Polygon":
                geoType = Polygon.class;
                break;
            case "MultiPolygon":
                geoType = MultiPolygon.class;
                break;
            }
            // 创建shape文件对象
            File file = new File(shpPath);
            Map<String, Serializable> params = new HashMap<String, Serializable>();
            params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL());
            ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);
            // 定义图形信息和属性信息
            SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
            tb.setCRS(DefaultGeographicCRS.WGS84);
            tb.setName("shapefile");
            tb.add("the_geom", geoType);// 类型,Point/MultiPoint/LineString/MultiLineString/Polygon/MultiPolygon
            Iterator propertiesIter = properties.iterator();
            // 设置属性
            while (propertiesIter.hasNext()) {
                String str = propertiesIter.next();
                tb.add(str, String.class);// 此处设置为string,如需修改请自行改写代码
            }

            ds.createSchema(tb.buildFeatureType());
            // 设置编码
            Charset charset = Charset.forName("GBK");
            ds.setCharset(charset);
            // 设置Writer
            FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(ds.getTypeNames()[0],
                    Transaction.AUTO_COMMIT);

            for (int i = 0, len = features.size(); i < len; i++) {
                String strFeature = features.get(i).toString();
                Reader reader = new StringReader(strFeature);
                SimpleFeature feature = writer.next();
                switch (strType) {
                case "Point":
                    feature.setAttribute("the_geom", gjson.readPoint(reader));
                    break;
                case "MultiPoint":
                    feature.setAttribute("the_geom", gjson.readMultiPoint(reader));
                    break;
                case "LineString":
                    feature.setAttribute("the_geom", gjson.readLine(reader));
                    break;
                case "MultiLineString":
                    feature.setAttribute("the_geom", gjson.readMultiLine(reader));
                    break;
                case "Polygon":
                    feature.setAttribute("the_geom", gjson.readPolygon(reader));
                    break;
                case "MultiPolygon":
                    feature.setAttribute("the_geom", gjson.readMultiPolygon(reader));
                    break;
                }
                Iterator propertiesset = properties.iterator();
                while (propertiesset.hasNext()) {
                    String str = propertiesset.next();
                    JSONObject featurei = JSONObject.fromObject(features.get(i).toString());
                    feature.setAttribute(str, JSONObject.fromObject(featurei.get("properties")).get(str));
                }
                writer.write();
            }
            writer.close();
            ds.dispose();
            map.put("status", "success");
            map.put("message", shpPath);
        } catch (Exception e) {
            map.put("status", "failure");
            map.put("message", e.getMessage());
            e.printStackTrace();
        }
        return map;
    }

    /**
     * shp转换为Geojson
     * 
     * @param shpPath
     * @return
     */
    public Map shape2Geojson(String shpPath, String jsonPath) {
        Map map = new HashMap();

        FeatureJSON fjson = new FeatureJSON();

        try {
            StringBuffer sb = new StringBuffer();
            sb.append("{\"type\": \"FeatureCollection\",\"features\": [");

            File file = new File(shpPath);
            ShapefileDataStore shpDataStore = null;

            shpDataStore = new ShapefileDataStore(file.toURL());
            // 设置编码
            Charset charset = Charset.forName("GBK");
            shpDataStore.setCharset(charset);
            String typeName = shpDataStore.getTypeNames()[0];
            SimpleFeatureSource featureSource = null;
            featureSource = shpDataStore.getFeatureSource(typeName);
            SimpleFeatureCollection result = featureSource.getFeatures();
            SimpleFeatureIterator itertor = result.features();
            StringBuffer array = new StringBuffer();
            while (itertor.hasNext()) {
                SimpleFeature feature = itertor.next();
                StringWriter writer = new StringWriter();
                fjson.writeFeature(feature, writer);
                array.append(writer.toString());
                array.append(",");
            }
            // 删除多余的逗号
            array.deleteCharAt(array.length() - 1);
            itertor.close();
            sb.append(array.toString());
            sb.append("]}");

            // 写入文件
            File f = new File(jsonPath);// 新建文件
            try {
                BufferedWriter bw = new BufferedWriter(new FileWriter(f));
                bw.write(sb.toString());
                bw.flush();
                bw.close();
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }

            map.put("status", "success");
            map.put("message", sb.toString());
        } catch (Exception e) {
            map.put("status", "failure");
            map.put("message", e.getMessage());
            e.printStackTrace();

        }
        return map;
    }

    /**
     * 工具类测试方法
     * 
     * @param args
     */
    public static void main(String[] args) {
        shpTogeojson fileFormat = new shpTogeojson();
        long start = System.currentTimeMillis();
        // shape2Geojson
//      String shpPath = "D:/geojsonTest/gaosu.shp";
//      String jsonPath = "D:/geojsonTest/gaosu.geojson1";
//      Map map = fileFormat.shape2Geojson(shpPath, jsonPath);

        // geojson2Shape
        String shpPath = "D:/geojsonTest/gaosu1.shp";
        String jsonPath = "D:/geojsonTest/gaosu.geojson";
        Map map = fileFormat.geojson2Shape(jsonPath, shpPath);

        System.out.println(shpPath +" "+ jsonPath + ",共耗时" + (System.currentTimeMillis() - start) + "ms");
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容