Spring-Boot ? ShapeFile文件讀寫工具類+接口調用
阿新 • • 發佈:2018-10-25
void while har ble mage cto next() bound 添加
一、項目目錄結構樹
二、項目啟動
三、往指定的shp文件裏寫內容
(1) json數據【Post】
{ "name":"test", "path":"c:/test", "geom":"MULTIPOLYGON(((101.870371 25.19228,101.873633 25.188183,101.880564 25.184416,101.886808 25.186028,101.892043 25.189969,101.896592 25.190163,101.903716 25.190785,101.905454 25.193464,101.899897 25.196202,101.894146 25.197911,101.891657 25.19826,101.886078 25.197658,101.884211145538 25.2007060137013,101.88172564506 25.1949712942389,101.87874 25.199619,101.874641 25.200998,101.868547 25.202415,101.863741 25.202415,101.85887 25.202842,101.854557 25.202182,101.852604 25.199736,101.852282 25.19628,101.854492 25.194183,101.855608 25.192668,101.863698 25.192105,101.870371 25.19228)))","id":1001, "des":"湖泊水面" }
(2)接口調用
(3)QGIS查看,驗證數據有效性
四、讀取指定shp文件,並顯示內容
(1)接口調用
(2)QGIS顯示北京故宮【shp文件在項目中的static文件夾下】
五、將指定的shp文件轉成image文件或流
(1) 接口調用 === 轉image【png】文件
c盤下查看
(2) 接口調用 === 轉image流,輸出到客戶端
六、核心工具類【ShpTools】
package com.appleyk.geotools; import com.appleyk.IO.StringTokenReader; import com.appleyk.pojos.ShpDatas; import com.appleyk.pojos.ShpInfo; import com.appleyk.result.ResponseMessage; import com.appleyk.result.ResponseResult; import com.vividsolutions.jts.geom.*;import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.Polygon; import org.geotools.data.*; import org.geotools.data.shapefile.ShapefileDataStore; import org.geotools.data.shapefile.ShapefileDataStoreFactory; import org.geotools.data.simple.SimpleFeatureSource; import org.geotools.feature.FeatureCollection; import org.geotools.feature.FeatureIterator; import org.geotools.feature.simple.SimpleFeatureTypeBuilder; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.map.FeatureLayer; import org.geotools.map.Layer; import org.geotools.map.MapContent; import org.geotools.referencing.crs.DefaultGeographicCRS; import org.geotools.renderer.lite.StreamingRenderer; import org.geotools.styling.SLD; import org.geotools.styling.Style; import org.geotools.swing.JMapFrame; import org.geotools.swing.data.JFileDataStoreChooser; import org.opengis.feature.Property; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.springframework.util.ResourceUtils; import javax.imageio.ImageIO; import javax.servlet.http.HttpServletResponse; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.io.Serializable; import java.nio.charset.Charset; import java.util.Collection; import java.util.HashMap; import java.util.Map; /** * <p>shapefile讀寫工具類</p> * @author Appleyk * @blob https://blog.csdn.net/appleyk * @date Created on 上午 11:54 2018-10-12 */ public class ShpTools { /** * 集合對象構造器【自定義的】 */ private static GeometryCreator gCreator = GeometryCreator.getInstance(); /** * 邊界 */ private static ReferencedEnvelope bounds; // 畫布的寬度 private static final int IMAGE_WIDTH = 2400; // 畫布的高度 private static final int IMAGE_HEIGHT = 1200; /** * 通過shp文件路徑,讀取shp內容 * @param filePath * @throws Exception */ public static ShpDatas readShpByPath(String filePath,Integer limit) throws Exception { // 一個數據存儲實現,允許從Shapefiles讀取和寫入 ShapefileDataStore shpDataStore = new ShapefileDataStore(new File(filePath).toURI().toURL()); // 設置編碼【防止中文亂碼】 shpDataStore.setCharset(Charset.forName("UTF-8")); // getTypeNames:獲取所有地理圖層,這裏我只取第一個【如果是數據表,取出的就是表名】 String typeName = shpDataStore.getTypeNames()[0]; System.out.println("shp【圖層】名稱:"+typeName); FeatureCollection<SimpleFeatureType, SimpleFeature> result = getFeatures(shpDataStore, typeName); // 叠代特征集合 FeatureIterator<SimpleFeature> iterator = result.features(); ShpDatas shpDatas = new ShpDatas(); shpDatas.setName(typeName); shpDatas.setShpPath(filePath); buildShpDatas(limit, iterator, shpDatas); iterator.close(); return shpDatas; } /** * 根據數據源及圖層名稱拿到特征集合 * @param shpDataStore * @param typeName * @return * @throws IOException */ private static FeatureCollection<SimpleFeatureType, SimpleFeature> getFeatures(ShapefileDataStore shpDataStore, String typeName) throws IOException { // 通過此接口可以引用單個shapefile、數據庫表等。與數據存儲進行比較和約束 FeatureSource<SimpleFeatureType, SimpleFeature> featureSource = shpDataStore.getFeatureSource(typeName); // 一個用於處理FeatureCollection的實用工具類。提供一個獲取FeatureCollection實例的機制 FeatureCollection<SimpleFeatureType, SimpleFeature> result = featureSource.getFeatures(); System.out.println("地理要素【記錄】:"+result.size()+"個"); System.out.println("=================================="); return result; } /** * 構建shpDatas對象 * @param limit * @param iterator * @param shpDatas */ private static void buildShpDatas(Integer limit, FeatureIterator<SimpleFeature> iterator, ShpDatas shpDatas) { // 這裏我們只叠代前limit個 int stop = 0; while (iterator.hasNext()) { if (stop > limit) { break; } // 拿到一個特征 SimpleFeature feature = iterator.next(); // 取出特征裏面的屬性集合 Collection<Property> p = feature.getProperties(); // 遍歷屬性集合 Map<String,Object> prop = new HashMap<>(); for (Property pro : p) { String key = pro.getName().toString(); String val = pro.getValue().toString(); prop.put(key, val); System.out.println("key【字段】:"+key+"\t|| value【值】:"+val); } System.out.println("\n============================ 序號:"+stop+"\n"); shpDatas.addProp(prop); stop++; } // end 最外層 while } /** * 將一個幾何對象寫進shapefile * @param filePath * @param geometry */ public static void writeShpByGeom(String filePath, Geometry geometry) throws Exception{ ShapefileDataStore ds = getshpDS(filePath, geometry); FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(ds.getTypeNames()[0], Transaction.AUTO_COMMIT); // Interface SimpleFeature:一個由固定列表值以已知順序組成的SimpleFeatureType實例。 SimpleFeature feature = writer.next(); feature.setAttribute("name", "XXXX名稱"); feature.setAttribute("path", "c:/test"); feature.setAttribute("the_geom", geometry); feature.setAttribute("id", 1010L); feature.setAttribute("des", "XXXX描述"); System.out.println("========= 寫入【"+geometry.getGeometryType()+"】成功 !========="); // 寫入 writer.write(); // 關閉 writer.close(); // 釋放資源 ds.dispose(); } /** * 將一個幾何對象寫進shapefile * @param shpInfo */ public static ResponseResult writeShpByGeom(ShpInfo shpInfo) throws Exception{ // 特殊字符串解析器 StringTokenReader reader = new StringTokenReader(); // 根據幾何對象的wkt字符串,反解【解析】成Geometry對象 Geometry geometry = reader.read(shpInfo.getGeom()); // 拿到shp對象所在的目錄【文件夾】 String path = shpInfo.getPath(); File file = new File(path); if(!file.exists()){ file.mkdir(); } if(!file.isDirectory()){ return new ResponseResult(ResponseMessage.BAD_REQUEST,"path不是有效的文件夾" ); } String filePath = shpInfo.getPath()+"/"+shpInfo.getName()+".shp"; ShapefileDataStore ds = getshpDS(filePath, geometry); String typeName = ds.getTypeNames()[0]; FeatureWriter<SimpleFeatureType, SimpleFeature> writer ; if(shpInfo.isAppendWrite()){ // 追加寫幾何對象 writer = ds.getFeatureWriterAppend(typeName, Transaction.AUTO_COMMIT); }else{ // 覆蓋寫幾何對象 writer = ds.getFeatureWriter(typeName, Transaction.AUTO_COMMIT); } // Interface SimpleFeature:一個由固定列表值以已知順序組成的SimpleFeatureType實例。 SimpleFeature feature = writer.next(); feature.setAttribute("name", shpInfo.getName()); feature.setAttribute("path", shpInfo.getPath()); feature.setAttribute("the_geom", geometry); feature.setAttribute("id", shpInfo.getId()); feature.setAttribute("des", shpInfo.getDes()); System.out.println("========= 寫入【"+geometry.getGeometryType()+"】成功 !========="); // 寫入 writer.write(); // 關閉 writer.close(); // 釋放資源 ds.dispose(); // 返回創建成功後的shp文件路徑 return new ResponseResult(ResponseMessage.OK,filePath); } /** * 拿到配置好的DataStore * @param filePath * @param geometry * @return * @throws IOException */ private static ShapefileDataStore getshpDS(String filePath, Geometry geometry) throws IOException { // 1.創建shape文件對象 File file = new File(filePath); Map<String, Serializable> params = new HashMap<>(); // 2、用於捕獲參數需求的數據類 URLP:url to the .shp file. params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL()); // 3、創建一個新的數據存儲【如果存在,則不創建】 ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params); // 4、定義圖形信息和屬性信息 -- SimpleFeatureTypeBuilder 構造簡單特性類型的構造器 SimpleFeatureTypeBuilder tBuilder = new SimpleFeatureTypeBuilder(); // 5、設置 -- WGS84:一個二維地理坐標參考系統,使用WGS84數據 tBuilder.setCRS(DefaultGeographicCRS.WGS84); tBuilder.setName("shapefile"); // 添加名稱 tBuilder.add("name", String.class); // 添加shp所在目錄名稱 tBuilder.add("path", String.class); // 添加 一個幾何對象 tBuilder.add("the_geom", geometry.getClass()); // 添加一個id tBuilder.add("id", Long.class); // 添加描述 tBuilder.add("des", String.class); // 設置此數據存儲的特征類型 ds.createSchema(tBuilder.buildFeatureType()); // 設置編碼 ds.setCharset(Charset.forName("UTF-8")); return ds; } /** * 打開shp文件,獲取地圖內容 * @param filePath 文件路徑 * @param isOpenByChoose 是否自定義打開shp文件 * @throws Exception */ public static MapContent getMapContentByPath(String filePath,boolean isOpenByChoose,String color) throws Exception{ File file; if(isOpenByChoose){ // 1.1、 數據源選擇 shp擴展類型的 file = JFileDataStoreChooser.showOpenFile("shp", null); }else{ // 1.2、根據路徑拿到文件對象 file = new File(filePath); } if(file==null){ return null; } // 2、得到打開的文件的數據源 FileDataStore store = FileDataStoreFinder.getDataStore(file); // 3、設置數據源的編碼,防止中文亂碼 ((ShapefileDataStore)store).setCharset(Charset.forName("UTF-8")); /** * 使用FeatureSource管理要素數據 * 使用Style(SLD)管理樣式 * 使用Layer管理顯示 * 使用MapContent管理所有地圖相關信息 */ // 4、以java對象的方式訪問地理信息 -- 簡單地理要素 SimpleFeatureSource featureSource = store.getFeatureSource(); bounds = featureSource.getBounds(); // 5、創建映射內容,並將我們的shapfile添加進去 MapContent mapContent = new MapContent(); // 6、設置容器的標題 mapContent.setTitle("Appleyk‘s GeoTools"); Color color1; if(color == null || "".equals(color)){ color1 = Color.BLACK; }else if("red".equals(color)){ color1 = Color.RED; }else if("green".equals(color)){ color1 = Color.GREEN; }else if("blue".equals(color)){ color1 = Color.BLUE; }else{ color1 = Color.ORANGE; } // 7、創建簡單樣式 【顏色填充】 Style style = SLD.createSimpleStyle(featureSource.getSchema(),color1); // 8、顯示【shapfile地理信息+樣式】 Layer layer = new FeatureLayer(featureSource, style); // 9、將顯示添加進map容器 mapContent.addLayer(layer); return mapContent; } public static void showMap(MapContent mapContent){ JMapFrame.showMap(mapContent); } /** * shp文件轉Image【格式定png】 * @param shpFilePath shp目標文件 * @param destImagePath 轉成圖片的文件 == 如果沒有,轉成的圖片寫進response輸出流裏 * @param response 響應流 * @throws Exception */ public static void shp2Image(String shpFilePath,String destImagePath,String color, HttpServletResponse response) throws Exception{ // 流渲染器 StreamingRenderer renderer = new StreamingRenderer(); MapContent mapContent = getMapContentByPath(shpFilePath,false,color ); renderer.setMapContent(mapContent); Rectangle imageBounds = new Rectangle(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT); BufferedImage dumpImage = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB); Graphics2D g2d = dumpImage.createGraphics(); g2d.fillRect(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); renderer.paint(g2d, imageBounds, bounds); g2d.dispose(); if(destImagePath == null || "".equals(destImagePath)){ ImageIO.write(dumpImage, "png", response.getOutputStream()); }else{ ImageIO.write(dumpImage, "png", new File(destImagePath+".png")); } } public static void main(String[] args) throws Exception{ File file = ResourceUtils.getFile("classpath:static/shpTest[Point]/dp_tl.shp"); // 從shp文件裏面讀取屬性信息 readShpByPath(file.getAbsolutePath(),10); System.out.println("=================下面開始往shp文件裏面寫幾何對象==================="); // 先創建文件夾test String filePath = "C:/test/test.shp"; String pointWkt="POINT (120.76164848270959 31.22001141278534)"; Point point = gCreator.createPointByWKT(pointWkt); // Polygon【面】 String polygonWkt="POLYGON ((103.859188 34.695908, 103.85661 34.693788, 103.862027 34.69259, 103.863709 34.695078, 103.859188 34.695908))"; Polygon polygon = gCreator.createPolygonByWKT(polygonWkt); // LineString【線】 String linestringWkt="LINESTRING(113.511315990174 41.7274734296674,113.51492087909 41.7284983348307,113.516079593384 41.727649586406,113.515907932007 41.7262243043929,113.514019656861 41.7247989907606,113.512131381714 41.7250872589898,113.51138036319 41.7256637915682,113.511315990174 41.7274734296674)"; LineString lineString = gCreator.createLineByWKT(linestringWkt); // MultiPolygon【多面】 String multiPolyWkt = "MULTIPOLYGON(((101.870371 25.19228,101.873633 25.188183,101.880564 25.184416,101.886808 25.186028,101.892043 25.189969,101.896592 25.190163,101.903716 25.190785,101.905454 25.193464,101.899897 25.196202,101.894146 25.197911,101.891657 25.19826,101.886078 25.197658,101.884211145538 25.2007060137013,101.88172564506 25.1949712942389,101.87874 25.199619,101.874641 25.200998,101.868547 25.202415,101.863741 25.202415,101.85887 25.202842,101.854557 25.202182,101.852604 25.199736,101.852282 25.19628,101.854492 25.194183,101.855608 25.192668,101.863698 25.192105,101.870371 25.19228)))"; MultiPolygon multiPolygon = gCreator.createMulPolygonByWKT(multiPolyWkt); // 幾何對象的範圍【矩形邊界】 Envelope envelope = polygon.getEnvelopeInternal(); System.out.println(envelope); // 往shp文件裏面寫幾何對象 writeShpByGeom(filePath,point); } }
七、聯系我
CSDN名: Appleyk
CSDN博客:https://blog.csdn.net/Appleyk
本篇CSDN對應博文:https://blog.csdn.net/Appleyk/article/details/83376510
Spring-Boot ? ShapeFile文件讀寫工具類+接口調用