GeoTools应用:往shape文件中写GIS图层数据(5)


#一、环境准备
装配GeoTools有两种方式,一种是配置maven工程的pom文件(配置方式参考官网),另一种是下载geotools的jar包到本地导入依赖。我采用的是下载jar的方式,下载路径:https://sourceforge.net/projects/geotools/files/

#二、实现功能
本章要描述的功能是如何将GIS对象数据写入shape文件。下面以Point对象为例,线和多边形的处理方式类似。

#三、样例代码

##1、ShapeFieldInfo定义

package com.elon.model;

import java.io.Serializable;

/**
 * Shape文件字段信息模型。
 * 
 * @author elon
 * @version 2018年6月24日
 */
public class ShapeFieldInfo implements Serializable {

    private static final long serialVersionUID = 6947403344262247581L;
    
    /**
     * 字段名称
     */
    private String fieldName = "";
    
    /**
     * 字段类型
     */
    private Class<?> fieldType = null;
    
    public ShapeFieldInfo(String fieldName, Class<?> fieldType) {
        this.fieldName = fieldName;
        this.fieldType = fieldType;
    }
    
    @Override
    public String toString() {
        return "fieldName:" + fieldName + "|fieldType:" + fieldType.getName();
    }

    public String getFieldName() {
        return fieldName;
    }

    public void setFieldName(String fieldName) {
        this.fieldName = fieldName;
    }

    public Class<?> getFieldType() {
        return fieldType;
    }

    public void setFieldType(Class<?> fieldType) {
        this.fieldType = fieldType;
    }
}

##2、定义GIS对象的基础模型

package com.elon.model.gismodel;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.elon.constant.EnumGISObjectType;
import com.elon.model.ShapeFieldInfo;

/**
 * GIS对象基类定义。
 * 
 * @author elon
 * @version 2018年6月26日
 */
public class GISObjectBase implements Serializable {
   
    private static final long serialVersionUID = -6147262367078689317L;
    
    /**
     * 对象类型枚举
     */
    private final EnumGISObjectType type;
    
    /**
     * 属性列信息
     */
    private List<ShapeFieldInfo> attrFieldList = new ArrayList<>();
    
    /**
     * 属性值信息<属性名称, 属性值>
     */
    private Map<String, Object> attributeMap = new HashMap<>();
    
    protected GISObjectBase(EnumGISObjectType type,
            List<ShapeFieldInfo> attrFieldList){
        this.type = type;
        this.attrFieldList = attrFieldList;
    }

    public EnumGISObjectType getType() {
        return type;
    }
    
    public Map<String, Object> getAttributeMap() {
        return attributeMap;
    }

    public void setAttributeMap(Map<String, Object> attributeMap) {
        this.attributeMap = attributeMap;
    }
    
    public void addAttribute(String attrName, Object value) {
        attributeMap.put(attrName, value);
    }

    public List<ShapeFieldInfo> getAttrFieldList() {
        return attrFieldList;
    }

    public void setAttrFieldList(List<ShapeFieldInfo> attrFieldList) {
        this.attrFieldList = attrFieldList;
    }
}

##3、定义GISPoint的模型

package com.elon.model.gismodel;

import java.util.List;

import com.elon.constant.EnumGISObjectType;
import com.elon.model.ShapeFieldInfo;
import com.vividsolutions.jts.geom.Point;

/**
 * 点对象模型
 * @author elon
 * @version 2018年6月26日
 */
public class GISPoint extends GISObjectBase {

    private static final long serialVersionUID = 851468237977190995L;
    
    /**
     * 点geometry对象
     */
    private Point point = null;

    public GISPoint(Point point, List<ShapeFieldInfo> attrFieldList) {
        super(EnumGISObjectType.POINT, attrFieldList);
        this.point = point;
    }

    public Point getPoint() {
        return point;
    }

    public void setPoint(Point point) {
        this.point = point;
    }
}

##4、写GISPoint对象到shape文件的代码

package com.elon.shape;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.geotools.data.FeatureSource;
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.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.opengis.feature.Property;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;

import com.elon.model.ShapeFieldInfo;
import com.elon.model.gismodel.GISObjectBase;
import com.elon.model.gismodel.GISPoint;
import com.elon.model.gismodel.GisLine;
import com.elon.model.gismodel.GisMultiPolygon;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Point;

/**
 * Shape文件操作公共类。
 * @author elon
 * @version 2018年6月24日
 */
public class ShapeUtils {
        
   /**
     * 写GIS对象到Shape文件。
     * @param dataStore shape文件源
     * @param gisObjectList 对象列表
     * @param attrFieldList 属性列表
     * @throws IOException
     */
    public static <T extends GISObjectBase> void writeShapeFile(ShapefileDataStore dataStore, List<T> gisObjectList,
            List<ShapeFieldInfo> attrFieldList) throws IOException {
        if (gisObjectList.isEmpty()) {
            return;
        }
        EnumGISObjectType type = gisObjectList.get(0).getType();

        // 设置图层对象属性
        SimpleFeatureType featureType = buildFeatureType(attrFieldList, type);
        dataStore.createSchema(featureType);
        dataStore.setCharset(Charset.forName("GBK"));

        List<SimpleFeature> featureList = buildFeatureList(gisObjectList, type, featureType);

        // 写数据
        SimpleFeatureSource featureSource = (SimpleFeatureSource) dataStore
                .getFeatureSource(dataStore.getTypeNames()[0]);
        SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;
        SimpleFeatureCollection collection = new ListFeatureCollection(featureType, featureList);

        Transaction transaction = new DefaultTransaction("create");
        featureStore.setTransaction(transaction);
        try {
            featureStore.addFeatures(collection);
            transaction.commit();
        } catch (Exception problem) {
            problem.printStackTrace();
            transaction.rollback();
        } finally {
            transaction.close();
        }
    }
    
    /**
     * 构建feature对象列表。
     * 
     * @param gisObjectList GIS对象列表
     * @param type feature类型
     * @param featureType
     * @return feature列表
     */
    private static <T extends GISObjectBase> List<SimpleFeature> buildFeatureList(List<T> gisObjectList,
            EnumGISObjectType type, SimpleFeatureType featureType){
        
        List<SimpleFeature> featureList = new ArrayList<>();
        SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(featureType);
        for (T gis : gisObjectList) {
            if (type == EnumGISObjectType.POINT) {
                featureBuilder.set("the_geom", ((GISPoint)gis).getPoint());
            }else if (type == EnumGISObjectType.LINE) {
                featureBuilder.set("the_geom", ((GISLine)gis).getLine());
            }else if (type == EnumGISObjectType.POLYGON) {
                featureBuilder.set("the_geom", ((GISMultiPolygon)gis).getPolygon());
            }else {
                System.out.println("Invalid gisobject type.");
                continue;
            }
            
            gis.getAttributeMap().forEach((k, v) -> featureBuilder.set(k, v));
            featureList.add(featureBuilder.buildFeature(null));
        }
        
        return featureList;
    }
    
    /**
     * 构建feature类型信息。
     * 
     * @param attrFieldList 属性字段列表
     * @param type gis对象类型
     * @return feature类型
     */
    private static SimpleFeatureType buildFeatureType(List<ShapeFieldInfo> attrFieldList,
            EnumGISObjectType type) {
        SimpleFeatureTypeBuilder sb = new SimpleFeatureTypeBuilder();
        sb.setCRS(DefaultGeographicCRS.WGS84);

        sb.setName("shape");
        attrFieldList.forEach((f) -> sb.add(f.getFieldName(), f.getFieldType()));
        if (type == EnumGISObjectType.POINT) {
            sb.add("the_geom", Point.class);            
        }else if (type == EnumGISObjectType.LINE) {
            sb.add("the_geom", MultiLineString.class); 
        }else if (type == EnumGISObjectType.POLYGON) {
            sb.add("the_geom", MultiPolygon.class);  
        }else {
            System.out.println("Invalid gisobject type.");
            return null;
        }
        
        return sb.buildFeatureType();
    }
    
    /**
     * 构建ShapeDataStore对象。
     * @param shpFilePath shape文件路径。
     * @return
     */
    public static ShapefileDataStore buildDataStore(String shpFilePath) {
        ShapefileDataStoreFactory factory = new ShapefileDataStoreFactory();
        try {
            ShapefileDataStore dataStore = (ShapefileDataStore) factory
                    .createDataStore(new File(shpFilePath).toURI().toURL());
            if (dataStore != null) {
                dataStore.setCharset(Charset.forName("UTF-8"));
            }
            return dataStore;
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }
}

##5、客户端调用代码

package com.elon;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.geotools.data.shapefile.ShapefileDataStore;

import com.elon.model.ShapeFieldInfo;
import com.elon.model.gismodel.GISPoint;
import com.elon.shape.ShapeUtils;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;

public class StartupGeoTools {
	public static void main(String[] args) throws IOException {
	    
	    String workSpacePath = System.getProperty("user.dir");
	    
        List<ShapeFieldInfo> attrFieldList = new ArrayList<>();
        attrFieldList.add(new ShapeFieldInfo("id", Integer.class));
        attrFieldList.add(new ShapeFieldInfo("name", String.class));
        
        GeometryFactory factory = new GeometryFactory();
        List<GISPoint> pointList = new ArrayList<>();
        
        GISPoint point1 = new GISPoint(factory.createPoint(new Coordinate(20.11, 35.22)), attrFieldList);
        point1.getAttributeMap().put("id", 6);
        point1.getAttributeMap().put("name", "111");
        pointList.add(point1);
        
        GISPoint point2 = new GISPoint(factory.createPoint(new Coordinate(50.121, 45.2222)), attrFieldList);
        point2.getAttributeMap().put("id", 8);
        point2.getAttributeMap().put("name", "222");
        pointList.add(point2);
        
        String shpFilePath2 = workSpacePath + File.separator + "shape/student/student.shp";
        ShapefileDataStore dataStore = ShapeUtils.buildDataStore(shpFilePath2);
	    ShapeUtils.writeShapeFile(dataStore, pointList, attrFieldList);
	    dataStore.dispose();
	    
	    System.out.println("Start GeoTools success!");
	}
}


student.shp是用QGIS建的一个点图层shape文件,有id和name这两个属性。

#四、补充说明
上面写shape文件的方式是全量写的方式,也就是说新增的数据会将旧数据覆盖,不会保留。

转载自:https://blog.csdn.net/ylforever/article/details/80935231

You may also like...