GeoTools Maven 依赖 官网地址
pom
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <geotools.version>18.4</geotools.version> </properties> <repositories> <repository> <id>osgeo</id> <name>OSGeo Release Repository</name> <url>https://repo.osgeo.org/repository/release/</url> <snapshots><enabled>false</enabled></snapshots> <releases><enabled>true</enabled></releases> </repository> <repository> <id>osgeo-snapshot</id> <name>OSGeo Snapshot Repository</name> <url>https://repo.osgeo.org/repository/snapshot/</url> <snapshots><enabled>true</enabled></snapshots> <releases><enabled>false</enabled></releases> </repository> </repositories> <dependency> <groupId>org.geotools</groupId> <artifactId>gt-shapefile</artifactId> <version>${geotools.version}</version> </dependency> <dependency> <groupId>org.geotools</groupId> <artifactId>gt-geojson</artifactId> <version>${geotools.version}</version> </dependency> <dependency> <groupId>org.geotools</groupId> <artifactId>gt-csv</artifactId> <version>${geotools.version}</version> </dependency> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.58</version> </dependency> import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONException; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.Polygon; import org.apache.commons.lang3.StringUtils; import org.geotools.data.DataUtilities; 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.SchemaException; import org.geotools.feature.simple.SimpleFeatureTypeBuilder; import org.geotools.referencing.crs.DefaultGeographicCRS; import org.opengis.feature.IllegalAttributeException; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import java.io.File; import java.io.Serializable; import java.nio.charset.Charset; import java.util.*; /** * @author Mr.superbeyone * @project cs-sys * @className ShpWriterUtil * @description * @date 2019-07-10 16:09 **/ public class ShpWriterUtil { /** * Json中存储坐标信息的key */ private static final String PLOT_TYPE = "plotType"; /** * Json中存储空间类型的key */ private static final String JSON_GEOM_KEY = "pts"; /** * the_geom can not be changed */ private static final String GEOM_KEY = "the_geom"; public static final String POINT = "POINT"; public static final String LINE = "LINE"; public static final String POLYGON = "POLYGON"; private static List<Map<String, String>> getShpFieldDataMap(String jsonData) throws Exception { /** * 需要重定义的 key */ jsonData = jsonData.replace(JSON_GEOM_KEY, GEOM_KEY); List list = new ArrayList(); JSONArray jsonArray = JSONArray.parseArray(jsonData); Iterator<Object> iterator = jsonArray.iterator(); while (iterator.hasNext()) { Map<String, Object> next = (Map<String, Object>) iterator.next(); next.remove("images"); list.add(next); } return list; } /** * 获取集合中的 key 全集 * * @param mapList 从json中获得的数据集 * @return key 全集 */ private static Set<String> getMaxKeyMap(List<Map<String, String>> mapList) { Set<String> keySet = new HashSet<>(); for (Map<String, String> stringMap : mapList) { for (Map.Entry entry : stringMap.entrySet()) { if (entry.getKey() == null) { continue; } String key = ((String) entry.getKey()).toUpperCase(); if (!keySet.contains(key)) { keySet.add(key); } } } keySet.add("ZIPCODE"); keySet.add("URL"); keySet.add("PRODATE"); keySet.remove(PLOT_TYPE.toUpperCase()); return keySet; } /** * 字符串转成空间字段所需的数组集合 * * @param str * @return */ private static Coordinate[] str2CoordinateArr(String str, String type) { List<Coordinate> coordinates = new ArrayList<>(); String[] strings = StringUtils.split(str, ","); for (int i = 0; i < strings.length; i++) { String[] split = StringUtils.split(strings[i], " "); if (split.length == 2) { coordinates.add(new Coordinate(Double.parseDouble(split[1].trim()), Double.parseDouble(split[0].trim()))); } } if (StringUtils.equals(type, POLYGON)) { coordinates.add(coordinates.get(0)); } return coordinates.toArray(new Coordinate[coordinates.size()]); } /** * 生成shp文件 * * @param filePath 文件路径 * @return shp文件 */ private static File generateFile(String filePath) { //创建shape文件对象 File root = new File(filePath); filePath += File.separator + root.getName(); if (!StringUtils.endsWithIgnoreCase(filePath, ".shp")) { filePath += ".shp"; } File file = new File(filePath); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } return file; } public static void shpWriter(String filePath, String jsonData, String geomType) { try { File file = generateFile(filePath); List<Map<String, String>> shpFieldDataMapList = getShpFieldDataMap(jsonData); Set<String> keys = getMaxKeyMap(shpFieldDataMapList); Map<String, Serializable> params = new HashMap<String, Serializable>(); params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL()); ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params); //定义图形信息和属性信息 SimpleFeatureTypeBuilder simpleFeatureTypeBuilder = new SimpleFeatureTypeBuilder(); simpleFeatureTypeBuilder.setCRS(DefaultGeographicCRS.WGS84); simpleFeatureTypeBuilder.setName("shapeFile"); switch (geomType.toUpperCase()) { case POINT: simpleFeatureTypeBuilder.add(GEOM_KEY, Point.class); break; case LINE: simpleFeatureTypeBuilder.add(GEOM_KEY, LineString.class); break; case POLYGON: simpleFeatureTypeBuilder.add(GEOM_KEY, Polygon.class); break; default: throw new RuntimeException("空间字段类型错误"); } for (String key : keys) { simpleFeatureTypeBuilder.add(key, String.class); } ds.createSchema(simpleFeatureTypeBuilder.buildFeatureType()); ds.setCharset(StandardCharsets.UTF_8); //设置Writer FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(ds.getTypeNames()[0], Transaction.AUTO_COMMIT); //写下一条 SimpleFeature feature; for (Map<String, String> stringMap : shpFieldDataMapList) { feature = writer.next(); for (Map.Entry<String, String> entry : stringMap.entrySet()) { String key = entry.getKey(); //Json中存储坐标信息的key跳过导出 if (key == null || StringUtils.equals(key, PLOT_TYPE)) { continue; } if (key.length() > 10) { key = StringUtils.substring(key, 0, 10); } key = key.toUpperCase(); String value = entry.getValue() == null ? "" : entry.getValue(); if (StringUtils.equals(key, GEOM_KEY.toUpperCase())) { if (StringUtils.equals(geomType, POINT)) { String[] split = value.split(" "); if (split.length == 2) { Coordinate coordinate = new Coordinate(Double.parseDouble(split[1].trim()), Double.parseDouble(split[0].trim())); feature.setAttribute(GEOM_KEY, new GeometryFactory().createPoint(coordinate)); } } else if (StringUtils.equals(geomType, LINE)) { LineString line = new GeometryFactory().createLineString(str2CoordinateArr(value, LINE)); feature.setAttribute(GEOM_KEY, line); } else if (StringUtils.equals(geomType, POLYGON)) { Polygon polygon = new GeometryFactory().createPolygon(str2CoordinateArr(value, POLYGON)); feature.setAttribute(GEOM_KEY, polygon); } } else { feature.setAttribute(key, value); } } } writer.write(); writer.close(); ds.dispose(); } catch (Exception e) { e.printStackTrace(); } } private static void shpReader(String filePath) throws Exception { ShpFiles shpFiles = new ShpFiles(filePath); ShapefileReader reader = new ShapefileReader(shpFiles, false, true, new GeometryFactory(), false); try { while (reader.hasNext()) { System.out.println(reader.nextRecord().shape()); } } finally { reader.close(); } } public static void main(String[] args) throws Exception { //读取刚写完shape文件的图形信息 String filePath = ""; filePath = "F:\\shp\\tmp\\FMEW\\3333.shp"; // String timeMillis = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")); // filePath = "F:\\shp\\tmp" + File.separator + timeMillis + File.separator + timeMillis; // File file = new File(filePath); // if (!file.exists()) { // file.getParentFile().mkdirs(); // } // shpWriter(filePath, "jsonStr", POLYGON); shpReader(filePath); } } public void test(){ String saveRoot = "D:\\test"; ShpWriterUtil.shpWriter(saveRoot + File.separator + "point", pointJson, ShpWriterUtil.POINT); } 压缩工具类 import java.io.*; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class FilePackUtil { private static final int BUFFER_SIZE = 2 * 1024; public static void pack(File src, File dest) { if (!dest.exists()) { dest.mkdirs(); } FileOutputStream outputStream = null; try { outputStream = new FileOutputStream(new File(dest, src.getName() + ".zip")); } catch (FileNotFoundException e) { e.printStackTrace(); } pack(src, outputStream, true); } /** * 压缩成ZIP 方法1 * * @param srcFile 压缩文件夹路径 * @param out 压缩文件输出流 * @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构; * false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败) * @throws RuntimeException 压缩失败会抛出运行时异常 */ public static void pack(File srcFile, OutputStream out, boolean KeepDirStructure) throws RuntimeException { ZipOutputStream zos = null; try { zos = new ZipOutputStream(out); compress(srcFile, zos, srcFile.getName(), KeepDirStructure); } catch (Exception e) { throw new RuntimeException("zip error from ZipUtils", e); } finally { if (zos != null) { try { zos.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 压缩成ZIP 方法2 * * @param srcFiles 需要压缩的文件列表 * @param out 压缩文件输出流 * @throws RuntimeException 压缩失败会抛出运行时异常 */ public static void pack(List<File> srcFiles, OutputStream out) throws RuntimeException { long start = System.currentTimeMillis(); ZipOutputStream zos = null; try { zos = new ZipOutputStream(out); for (File srcFile : srcFiles) { byte[] buf = new byte[BUFFER_SIZE]; zos.putNextEntry(new ZipEntry(srcFile.getName())); int len; FileInputStream in = new FileInputStream(srcFile); while ((len = in.read(buf)) != -1) { zos.write(buf, 0, len); } zos.closeEntry(); in.close(); } long end = System.currentTimeMillis(); System.out.println("压缩完成,耗时:" + (end - start) + " ms"); } catch (Exception e) { throw new RuntimeException("zip error from ZipUtils", e); } finally { if (zos != null) { try { zos.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 递归压缩方法 * * @param sourceFile 源文件 * @param zos zip输出流 * @param name 压缩后的名称 * @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构; * false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败) * @throws Exception */ private static void compress(File sourceFile, ZipOutputStream zos, String name, boolean KeepDirStructure) throws Exception { byte[] buf = new byte[BUFFER_SIZE]; if (sourceFile.isFile()) { // 向zip输出流中添加一个zip实体,构造器中name为zip实体的文件的名字 zos.putNextEntry(new ZipEntry(name)); // copy文件到zip输出流中 int len; FileInputStream in = new FileInputStream(sourceFile); while ((len = in.read(buf)) != -1) { zos.write(buf, 0, len); } // Complete the entry zos.closeEntry(); in.close(); } else { File[] listFiles = sourceFile.listFiles(); if (listFiles == null || listFiles.length == 0) { // 需要保留原来的文件结构时,需要对空文件夹进行处理 if (KeepDirStructure) { // 空文件夹的处理 zos.putNextEntry(new ZipEntry(name + "/")); // 没有文件,不需要文件的copy zos.closeEntry(); } } else { for (File file : listFiles) { // 判断是否需要保留原来的文件结构 if (KeepDirStructure) { // 注意:file.getName()前面需要带上父文件夹的名字加一斜杠, // 不然最后压缩包中就不能保留原来的文件结构,即:所有文件都跑到压缩包根目录下了 compress(file, zos, name + "/" + file.getName(), KeepDirStructure); } else { compress(file, zos, file.getName(), KeepDirStructure); } } } } } } 解析的JSON数据格式 [ { "extend":{}, "userdef":[ { "value":"190108", "key":"category" }, { "value":"104.0541", "key":"lng" }, { "value":"30.64697", "key":"lat" }, { "value":"武侯祠", "key":"address" }, { "value":"", "key":"url" }, { "value":"", "key":"descrip" } ], "basic":{ "imd":"8", "plotType":"point", "nid":"", "pid":"", "source":"", "statecode":"1", "pts":"30.64697 104.0541", "elemid":"6.20075047E9", "zipcode":"0", "ename":"", "sname":"", "telphone":"", "name":"XX小组办公室", "clasid":"", "tag":"0", "gb":"156510107", "sename":"" } } ]