JAVA 读取shp数据,shp导入,导出工具 您所在的位置:网站首页 java读取mdb文件处理编码 JAVA 读取shp数据,shp导入,导出工具

JAVA 读取shp数据,shp导入,导出工具

2024-07-06 22:07| 来源: 网络整理| 查看: 265

1.问题,在Gis的项目中我们会经常用到有关于shp的读取,导入导出的功能,为此公司大牛做了一个工具,简化了很多操作,只要学会应用即可

2.使用

ShapeTools,工具类,里面封装了各种处理shp的方法 public class ShapeTools { /** * shp文件定义字段时,字段名长度不能多于10个字符 */ private final int FEILD_LENGTH_LIMIT = 10; /** * shp文件定义字段时,空间属性字段必须是the_geom */ private final String GEOM_FIELD_NAME = "the_geom"; /** * 2017年11月23日 * 读取shp文件,把名称和fid保存到ES中, * @param fileName * @param url 例: http://localhost:9200/dmdz2017/poi/_bulk * 通过http _bulk命令批量建索引的方式 * @throws MalformedURLException * @throws IOException */ public void readShpToES(String fileName, String url) throws MalformedURLException, IOException { ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory(); WKTReader reader = new WKTReader(); File file = new File(fileName); ShapefileDataStore sds = (ShapefileDataStore) dataStoreFactory.createDataStore(file.toURI().toURL()); sds.setCharset(Charset.forName("GBK")); List fs = new ArrayList(); SimpleFeatureSource featureSource = sds.getFeatureSource(); SimpleFeatureIterator iterator = featureSource.getFeatures().features(); Property per = null; while(iterator.hasNext()){ SimpleFeature feature = iterator.next(); Iterator it = feature.getProperties().iterator(); Map properties = new HashMap(); while(it.hasNext()){ per = it.next(); String key = per.getName().toString(); properties.put(key, per.getValue().toString()); } fs.add(properties); } shpToES(fs, url); } /** * 文件名加上时间戳 * @param fname * @return */ private String rename(String fname){ int index = fname.lastIndexOf("."); String temp = fname.substring(0, index) + System.currentTimeMillis(); temp += fname.substring(index); return temp; } /** * 使用Apache http建立ES索引 * @param fs * @param url http://localhost:9200/dmdz2017/poi/_bulk * @return * @throws IOException */ private boolean shpToES(List fs, String url) throws IOException{ if(null == url || "".equals(url)) return false; long startTime = System.currentTimeMillis(); PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(); CloseableHttpClient httpclient = HttpClients.custom().setConnectionManager(cm).build(); HttpPost httpPost = new HttpPost(url); StringBuilder sb = new StringBuilder(); // Map prs = null; for(int i = 0, total = fs.size(); i < total; i++){ prs = fs.get(i); sb.append("{\"create\":{\"_id\":\"").append(startTime + i).append("\"}}\n"); sb.append(toJson(prs)).append("\n"); //System.out.println(sb.toString()); if((i % 200) == 0 || i == total-1){ httpPost.setEntity(new StringEntity(sb.toString(), "utf-8")); CloseableHttpResponse response = httpclient.execute(httpPost); response.close(); sb = null; sb = new StringBuilder(); System.out.println("数据入库完成,总共"+total+",已完成" + i + ", 耗时 " + (System.currentTimeMillis() - startTime) + "毫秒"); } } httpclient.close(); return true; } private String toJson(Map ms){ if(null == ms) { return "{}"; } StringBuilder sb = new StringBuilder("{"); for(Iterator iterator = ms.keySet().iterator(); iterator.hasNext(); sb.append(",")){ String k = iterator.next(); sb.append("\"").append(k).append("\":\"") .append(ms.get(k)).append("\""); } sb.deleteCharAt(sb.lastIndexOf(",")); sb.append("}"); return sb.toString(); } /** * 一个测试创建shp的方法 * @throws SchemaException * @throws ParseException * @throws IOException */ @Deprecated protected void testCreateFeature() throws SchemaException, ParseException, IOException{ final SimpleFeatureType featureType = DataUtilities.createType("Location", "the_geom:MultiPolygon:4490," + "name:String," + "type:String," + "typeCode:String"); List features = new ArrayList(); SimpleFeatureBuilder sfb = new SimpleFeatureBuilder(featureType); WKTReader wktReader = new WKTReader(); Geometry g = wktReader.read("MULTIPOLYGON(((120.245550628244 30.3697319771691,120.245604273926 30.3693135531255,120.24339413664 30.3690667936267,120.243630170808 30.368079739938,120.24205303449 30.3678007917758,120.241409305793 30.3668673845079,120.241291288517 30.3659447050454,120.241838457153 30.3652902449766,120.24261093291 30.3647216149009,120.242857696301 30.3633590530615,120.242986442154 30.3626831362105,120.246097798899 30.3664382241636,120.249713410056 30.3696568698573,120.249788512627 30.3709336004773,120.249482741414 30.3710677121942,120.247229688992 30.3708906898944,120.247353069806 30.3699948315325,120.245513078403 30.3698285368174,120.245550628244 30.3697319771691,120.245550628244 30.3697319771691)),((120.250083554427 30.3672053292808,120.250094283151 30.367993898842,120.249713410056 30.3696568698573,120.247953884385 30.3681011910327,120.24685954468 30.3670712245555,120.247661524439 30.3666179298771,120.248780002808 30.365907142485,120.249450554592 30.366513321681,120.250083554427 30.3672053292808,120.250083554427 30.3672053292808,120.250083554427 30.3672053292808)))"); sfb.add(g); sfb.add("ming cheng"); sfb.add("lei xing"); sfb.add("type code"); features.add(sfb.buildFeature("idididi")); ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory(); Map params = new HashMap(); File f = new File("d:\\test.shp"); params.put("url", f.toURI().toURL()); params.put("create spatial index", Boolean.TRUE); ShapefileDataStore newDataStore = (ShapefileDataStore) dataStoreFactory.createNewDataStore(params); newDataStore.createSchema(featureType); String typeName = newDataStore.getTypeNames()[0]; SimpleFeatureSource featureSource = newDataStore.getFeatureSource(typeName); SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource; SimpleFeatureCollection collection = new ListFeatureCollection(featureType, features); Transaction transaction = new DefaultTransaction("create"); featureStore.setTransaction(transaction); featureStore.addFeatures(collection); transaction.commit(); } /** * 指定创建shp文件的字段属性,注意字段名称长度不能超过10个字符 * 2018年11月2日,除了空间属性外,此方法只能生成全字符类型的其他属性 * @param heads * @param geomName * @param geomClass * @return */ @Deprecated public SimpleFeatureTypeBuilder createFeatureTypeBuilder(String[] heads, String geomName, Class geomClass){ SimpleFeatureTypeBuilder sftb = new SimpleFeatureTypeBuilder(); for(String name : heads){ if(name.equals(geomName)){ sftb.add(GEOM_FIELD_NAME, geomClass); } else { sftb.add(name, String.class); } } return sftb; } /** * 2018年10月29日 * 如果是为了生成shp文件而调用此方法,注意字段名称长度不能超过10个字符 * @param clazz 有com.trgis.geotools.GeoJSON注解的空间类 * @return */ public SimpleFeatureTypeBuilder createFeatureTypeBuilder(Class clazz){ SimpleFeatureTypeBuilder sftb = new SimpleFeatureTypeBuilder(); String name = ((GeoJSON)clazz.getAnnotation(GeoJSON.class)).name(); if(null == name){ sftb.setName("feature"); } else { sftb.setName(name); } boolean hasGeometry = false; Field[] fs = clazz.getDeclaredFields(); for(Field f : fs){ GeoJSON g = f.getAnnotation(GeoJSON.class); if(null == g) continue; String field = g.field(); if("".equals(field)){ field = f.getName(); } if(!hasGeometry && g.isGeometry()) { hasGeometry = true; field = GEOM_FIELD_NAME; } Class type = g.type(); if(type == Object.class) sftb.add(field, f.getType()); else sftb.add(field, type); } if(!hasGeometry) throw new NullPointerException("GeoJSON : annotation must has geometry field"); return sftb; } /** * 将封装好的空间数据及属性写入到shp文件 * @param tb * @param list 每个属性对应的数据对象,属性名称不能超过10个字符 * @param filePath * @return * @throws IOException */ public boolean writeToShpFile(SimpleFeatureTypeBuilder tb, List list, String filePath) throws Exception { boolean b = false; Map params = new HashMap(); FileDataStoreFactorySpi factory = new ShapefileDataStoreFactory(); params.put(ShapefileDataStoreFactory.URLP.key, new File(filePath).toURI().toURL()); ShapefileDataStore ds = (ShapefileDataStore) factory.createNewDataStore(params); tb.setName("shapefile"); SimpleFeatureType sft = tb.buildFeatureType(); ds.createSchema(sft); ds.setCharset(Charset.forName("GBK")); FeatureWriter writer = ds.getFeatureWriter( Transaction.AUTO_COMMIT); //list中对象写入feature对象 for (int i = 0; i < list.size(); i++){ SimpleFeature feature = writer.next(); for(Map.Entry entry : list.get(i).entrySet()){ if(entry.getKey().length() > FEILD_LENGTH_LIMIT) throw new Exception("定义shp文件的属性字段名不能超过10个字符:" + entry.getKey()); if(null != feature.getProperty(entry.getKey())) feature.setAttribute(entry.getKey(), entry.getValue()); } } writer.write(); writer.close(); ds.dispose(); b = true; return b; } /** * 将空间对象集合保存到shp文件,空间对象必须是有GeoJSON注解的 * 2018年11月1日 * @param objs * @param filePath * @return * @throws Exception * @author 王风雨 */ public boolean writeToShpFromGeoJSON (List objs, String filePath) throws Exception { boolean b = false; if(objs.size() == 0) return b; Class clazz = objs.get(0).getClass(); GeoJSON g = objs.get(0).getClass().getAnnotation(GeoJSON.class); if(null == g) return b; SimpleFeatureTypeBuilder simpleFeatureTypeBuilder = new SimpleFeatureTypeBuilder(); simpleFeatureTypeBuilder.setName(g.name()); boolean hasGeometry = false; Field[] fields = clazz.getDeclaredFields(); Map fieldMap = new HashMap(); for(Field f : fields){ g = f.getAnnotation(GeoJSON.class); if(null == g) continue; String field = g.field(); if("".equals(field)){ field = f.getName(); } if(field.length() > FEILD_LENGTH_LIMIT) throw new Exception("定义shp文件的属性字段名不能超过10个字符" + field); if(!hasGeometry && g.isGeometry()) { hasGeometry = true; field = GEOM_FIELD_NAME; } Class type = g.type(); if(type == Object.class) simpleFeatureTypeBuilder.add(field, f.getType()); else simpleFeatureTypeBuilder.add(field, type); fieldMap.put(field, f.getName()); } if(!hasGeometry) throw new NullPointerException("GeoJSON : annotation must has geometry field"); List list = new ArrayList(); for(T t : objs){ Map obj = new HashMap(); for(Map.Entry fieldEntry : fieldMap.entrySet()){ Method method = clazz.getMethod(getMethodName(fieldEntry.getValue())); obj.put(fieldEntry.getKey(), method.invoke(t)); } list.add(obj); } b = writeToShpFile(simpleFeatureTypeBuilder, list, filePath); return b; } /** * 读取shp文件,返回对象集合 * @param filePath 文件名及全路径 * @param shpEntityBuilder feature对象转换成指定对象的接口 * @return * @throws Exception */ public List readShp(String filePath, ShpEntityBuilder shpEntityBuilder) throws Exception { ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory(); File file = new File(filePath); ShapefileDataStore sds = (ShapefileDataStore) dataStoreFactory.createDataStore(file.toURI().toURL()); sds.setCharset(Charset.forName("GBK")); SimpleFeatureIterator iterator = sds.getFeatureSource().getFeatures().features(); List datas = new ArrayList(); while (iterator.hasNext()){ T data = shpEntityBuilder.createEntity(iterator.next()); if(null != data) datas.add(data); } return datas; } /** * 将有GeoJSON注解的空间对象转换成SimpleFeature * @param obj 只针对有GeoJSON注解的字段 * @return * @throws IOException * @throws InvocationTargetException * @throws IllegalAccessException * @throws NoSuchMethodException */ public SimpleFeature toSimpleFeature(Object obj) throws IOException, InvocationTargetException, IllegalAccessException, NoSuchMethodException { Class clazz = obj.getClass(); SimpleFeatureTypeBuilder simpleFeatureTypeBuilder = createFeatureTypeBuilder(clazz); SimpleFeatureBuilder simpleFeatureBuilder = new SimpleFeatureBuilder(simpleFeatureTypeBuilder.buildFeatureType()); String id = null; Map values = new HashMap(); Field[] fields = clazz.getDeclaredFields(); for(Field field : fields){ GeoJSON g = field.getAnnotation(GeoJSON.class); if(null == g) continue; if(g.isID()){ Method method = clazz.getMethod(getMethodName(field.getName())); id = method.invoke(obj).toString(); } else { String fieldName = g.field(); if("".equals(fieldName)){ fieldName = field.getName(); } if(g.isGeometry()){ fieldName = GEOM_FIELD_NAME; } Method method = clazz.getMethod(getMethodName(field.getName())); values.put(fieldName, method.invoke(obj)); } } if(null == id) id = String.valueOf(System.currentTimeMillis()); SimpleFeature feature = simpleFeatureBuilder.buildFeature(id); for (Map.Entry entry : values.entrySet()){ feature.setAttribute(entry.getKey(), entry.getValue()); } return feature; } /** * 将空间类集合转换为FeatureCollection对象 * @param list 必须是有GeoJSON注解的空间类对象集合 * @return * @throws InvocationTargetException * @throws NoSuchMethodException * @throws IllegalAccessException * @throws IOException */ public SimpleFeatureCollection toSimpleFeatureCollection(List list) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException { DefaultFeatureCollection featureCollection = new DefaultFeatureCollection(); for(Object obj : list){ featureCollection.add(toSimpleFeature(obj)); } return featureCollection; } /** * 将有GeoJSON注解的空间对象转换成GeoJSON格式字符串 * @param obj 只针对有GeoJSON注解的字段 * @return * @throws IOException * @throws InvocationTargetException * @throws IllegalAccessException * @throws NoSuchMethodException */ public String toGeoJSON(Object obj) throws IOException, InvocationTargetException, IllegalAccessException, NoSuchMethodException { SimpleFeature feature = toSimpleFeature(obj); StringWriter writer = new StringWriter(); org.geotools.geojson.GeoJSON.write(feature, writer); return writer.toString(); } private String getMethodName(String field){ char first = field.charAt(0); String str = String.valueOf(first).toUpperCase(); String name = field.replaceFirst(String.valueOf(first), str); return "get" + name; } /** * 由Feature对象生成指定对象的接口,get Feature对象的属性值 set 到指定对象,前提是知道属性名称和数据类型的对应关系 * 例如 poi.setName(feature.getAttribute("name")) * @param */ public interface ShpEntityBuilder { /** * 根据字段对应关系,生成指定对象 * @param feature * @return * @throws Exception */ public T createEntity(SimpleFeature feature) throws Exception; } private String getSetMethodName(String field){ char first = field.charAt(0); String str = String.valueOf(first).toUpperCase(); String name = field.replaceFirst(String.valueOf(first), str); return "set" + name; } /** * 2018年11月2日 * 传递GeoJSON注释的类,使用注解的对应关系将shp文件读取的数据转换成指定对象 * @param clazz * @return */ public ShpEntityBuilder useDefaultBuilder(Class clazz) { return feature -> { GeoJSON g = (GeoJSON) clazz.getAnnotation(GeoJSON.class); if(null == g) throw new Exception("非GeoJSON注解的类"); T t = (T)clazz.newInstance(); Field[] fields = clazz.getDeclaredFields(); for(Field f : fields){ g = f.getAnnotation(GeoJSON.class); if(null == g) continue; Method method = clazz.getMethod(getSetMethodName(f.getName()), f.getType()); method.invoke(t, feature.getAttribute(g.isGeometry() ? GEOM_FIELD_NAME : "".equals(g.field()) ? f.getName() : g.field())); } return t; }; } } GeoJSON类 空间对象进行GeoJSON格式字符化 package com.trgis.geotools; import java.lang.annotation.*; /** * ShapeTools工具类的toGeoJSON方法对空间对象进行GeoJSON格式字符化时使用 * 用来生成org.geotools.feature.simple.SimpleFeatureTypeBuilder * 2018年10月29日 * @author */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.FIELD}) @Documented @Inherited public @interface GeoJSON { /** * 对应的SimpleFeatureTypeBuilder的setName方法参数,一般用在类上 * * @return */ public String name() default "feature"; /** * 用在空间对象的属性上,对应GeoJSON的属性名称 * 因为生成shp文件时,定义的shp字段名不能超过10个字符 * 所以当对象数据名长度超过10个字符时,必须指定field * @return */ public String field() default ""; /** * 在空间属性上使用应设置为true,且field需要设置为the_geom * @return */ public boolean isGeometry() default false; /** * ID属性上使用应设置为true * @return */ public boolean isID() default false; /** * 对象的Class类型,当int, double等时,需要声明为Integer,Double等 * @GeoJSON(type=Integer.class) * int count * @return */ public Class type() default Object.class; }

poi类

package com.trgis.geotools.model; import com.trgis.geotools.GeoJSON; import com.vividsolutions.jts.geom.Point; /** * 2018/11/2 * * @author */ @GeoJSON(name = "poi") public class Poi { /** * 类型是int double等时,必须指定type为包装类 */ @GeoJSON(isID = true, type = Integer.class) private int id; @GeoJSON(isGeometry = true) private Point location; @GeoJSON private String name; /** * 字段名称超过10个字符时,生成shp字段定义会出错 */ @GeoJSON(field = "the_pro", type = Double.class) private double the_properties; public int getId() { return id; } public void setId(int id) { this.id = id; } public Point getLocation() { return location; } public void setLocation(Point location) { this.location = location; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getThe_properties() { return the_properties; } public void setThe_properties(double the_properties) { this.the_properties = the_properties; } }

测试类

/** * 读取shp文件,封装成空间对象 * @throws Exception */ @Test public void testBouFromShp() throws Exception { String shpFile = "src\\main\\resources\\shp\\jiedao.shp"; //工具方法一readShp,从shp文件读取,封装成空间对象 List objs = shapeTools.readShp(shpFile, feature -> { GovBou bou = new GovBou(); //shp文件的所有属性:the_geom, FNAME, FEATUREGUI, SHAPE_Leng, SHAPE_Area Object geom = feature.getAttribute("the_geom"); String name = feature.getAttribute("FNAME").toString(); if(null != geom && geom instanceof MultiPolygon){ bou.setBou((MultiPolygon) geom); } bou.setName(name); bou.setId(String.valueOf(System.currentTimeMillis())); return bou; }); System.out.println("读取个数:" + objs.size()); //工具方法二toGeoJSON,空间对象转换层GeoJSON格式字符串,通过注解自动生成 String geojson = shapeTools.toGeoJSON(objs.get(0)); System.out.println(geojson); } /** * 从shp文件获取数据到对象也可以调用这个方法,利用类上的GeoJSON注解进行属性对应 */ @Test public void testBouFromShp2() throws Exception { String shpFile = "src\\main\\resources\\shp\\jiedao.shp"; List govBouList = shapeTools.readShp(shpFile, shapeTools.useDefaultBuilder(GovBou.class)); System.out.println("获取到Bou对象总数:"+govBouList.size()); } /** * 工具方法五:空间对象保存成shp文件 * @throws Exception */ @Test public void testWriteToShp2() throws Exception { WKTReader reader = new WKTReader(); List poiList = new ArrayList(); Poi p1 = new Poi(); p1.setId(1); p1.setName("aaa"); p1.setThe_properties(234.567); p1.setLocation((Point)reader.read("POINT(120.12 30.421)")); poiList.add(p1); String filePath = "src\\main\\resources\\shp\\poi1.shp"; boolean result = shapeTools.writeToShpFromGeoJSON(poiList, filePath); System.out.println(result ? "保存shp文件成功" : "失败"); //验证一下从生成的shp文件读取 List pois = shapeTools.readShp(filePath, shapeTools.useDefaultBuilder(Poi.class)); if(pois.size() > 0){ Poi p = pois.get(0); System.out.println(shapeTools.toGeoJSON(p)); } }

3.coding 地址:coding

https://e.coding.net/bitree/geotools-dev.git



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有