從數據庫中查詢數據並導出 ShapeFile 文件通用工具類封裝

pom依賴

部分pom依賴

具體導出操作工具類


import com.alibaba.fastjson.JSONArray;
import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jts.io.WKTReader;
import org.apache.commons.lang3.StringUtils;
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.shapefile.files.ShpFiles;
import org.geotools.data.shapefile.shp.ShapefileReader;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.geotools.referencing.crs.DefaultGeographicCRS;
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.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @author Mr.superbeyone
 * @project 
 * @className 
 * @description
 * @date 2019-08-29 11:49
 **/

public class ShpWriterUtil {

    /**
     * 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";


    /**
     * 寫shp文件
     *
     * @param filePath     shp 文件輸出路徑
     * @param dataList     數據集
     * @param geomType     空間類型
     * @param geomFieldKey list中表示空間字段 「 key 」 的 key
     * @param charset      字符編碼
     * @param keyToUpper   字段名大小寫 小於0:轉大寫,=0:保持原格式 大於0: 轉大寫
     * @param addKeySet    需要添加的 key 集合
     */
    public static File shpWriter(File filePath,
                                 List<Map<String, Object>> dataList,
                                 Set<String> fields,
                                 String geomType,
                                 String geomFieldKey,
                                 Charset charset,
                                 int keyToUpper,
                                 Set<String> removeKeySet,
                                 Set<String> addKeySet) {

        if (StringUtils.isBlank(geomFieldKey)) {
            geomFieldKey = "geometry";
        }
        File file = generateFile(filePath);
        try {

            Set<String> keys = getFieldsSet(fields, geomFieldKey, removeKeySet, addKeySet, keyToUpper);

            Map<String, Serializable> params = new HashMap<>();
            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, MultiPoint.class);
                    break;
                case LINE:
                    simpleFeatureTypeBuilder.add(GEOM_KEY, MultiLineString.class);
                    break;
                case POLYGON:
                    simpleFeatureTypeBuilder.add(GEOM_KEY, MultiPolygon.class);
                    break;
                default:
                    throw new RuntimeException("空間字段類型錯誤");
            }
            for (String key : keys) {
                simpleFeatureTypeBuilder.add(key, String.class);
            }
            ds.createSchema(simpleFeatureTypeBuilder.buildFeatureType());
            ds.setCharset(charset != null ? charset : StandardCharsets.UTF_8);
            //設置Writer
            FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(ds.getTypeNames()[0], Transaction.AUTO_COMMIT);
            generateCoordinateData(geomFieldKey, keyToUpper, dataList, writer, keys);
            writer.write();
            writer.close();
            ds.dispose();

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }

        return file;
    }

    private static List<Map<String, String>> getShpFieldDataMap(String jsonData, String geomValueKey, Map<String, String> needBeReplacedKeyMap, Set<String> removeKeySet) throws Exception {


        for (Map.Entry<String, String> entry : needBeReplacedKeyMap.entrySet()) {
            jsonData = jsonData.replace(entry.getKey(), entry.getValue());
        }
        /**
         * 需要重定義的 key
         */
        jsonData = jsonData.replace(geomValueKey, 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();
            if (removeKeySet != null) {
                for (String removeKey : removeKeySet) {
                    next.remove(removeKey);
                }
            }
            list.add(next);
        }
        return list;
    }

    /**
     * 獲取集合中的 key 全集
     *
     * @return key 全集
     */
    private static Set<String> getFieldsSet(Set<String> fields, String geomFieldKey, Set<String> removeKeySet, Set<String> addKeySet, int keyToUpper) {
        Set<String> keySet = new HashSet<>();
        for (String key : fields) {
            if (keyToUpper < 0) {
                keySet.add(key.toLowerCase());
            } else if (keyToUpper > 0) {
                keySet.add(key.toUpperCase());
            } else {
                keySet.add(key);
            }
        }
        if (addKeySet != null && addKeySet.size() > 0) {
            for (String key : addKeySet) {
                if (keyToUpper < 0) {
                    keySet.add(key.toLowerCase());
                } else if (keyToUpper > 0) {
                    keySet.add(key.toUpperCase());
                } else {
                    keySet.add(key);
                }
            }
        }
        if (keyToUpper < 0) {
            keySet.remove(geomFieldKey.toLowerCase());
        } else if (keyToUpper > 0) {
            keySet.remove(geomFieldKey.toUpperCase());
        } else {
            keySet.remove(geomFieldKey);
        }
        if (removeKeySet != null && removeKeySet.size() > 0) {
            for (String ignore : removeKeySet) {
                if (keyToUpper < 0) {
                    keySet.remove(ignore.toLowerCase());
                } else if (keyToUpper > 0) {
                    keySet.remove(ignore.toUpperCase());
                } else {
                    keySet.remove(ignore);
                }
            }
        }
        return keySet;
    }


    /**
     * 生成shp文件
     *
     * @param filePath 文件路徑
     * @return shp文件
     */
    private static File generateFile(File filePath) {
        //創建shape文件對象
        if (!StringUtils.endsWithIgnoreCase(filePath.getName(), ".shp")) {
            filePath = new File(filePath, filePath.getName() + ".shp");
        }
        if (!filePath.getParentFile().exists()) {
            filePath.getParentFile().mkdirs();
        }
        return filePath;
    }

    private static void generateCoordinateData(String geomFieldKey, int keyToUpper, List<Map<String, Object>> shpFieldDataMapList, FeatureWriter<SimpleFeatureType, SimpleFeature> writer, Set<String> keys) throws java.io.IOException {
        //寫下一條
        SimpleFeature feature;
        WKTReader wktReader = new WKTReader(JTSFactoryFinder.getGeometryFactory());
        for (Map<String, Object> stringMap : shpFieldDataMapList) {
            feature = writer.next();

            for (Map.Entry<String, Object> entry : stringMap.entrySet()) {

                String key = entry.getKey();
                if (key == null) {
                    continue;
                }
                if (keyToUpper < 0) {
                    key = key.toLowerCase();
                } else if (keyToUpper > 0) {
                    key = key.toUpperCase();
                }
                if (!keys.contains(key)) {
                    continue;
                }

                if (key.length() > 10) {
                    key = StringUtils.substring(key, 0, 10);
                }
                String value = entry.getValue() == null ? "" : entry.getValue().toString();
                try {
                    if (StringUtils.equalsIgnoreCase(key, geomFieldKey)) {
                        if (StringUtils.isNotBlank(value)) {
                            Geometry geometry = wktReader.read(value);
                            feature.setAttribute(GEOM_KEY, geometry);
                        } else {
                            feature.setAttribute(GEOM_KEY, null);
                        }
                    } else {
                        feature.setAttribute(key, value);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

導出工具類二次封裝

import com.tdt.cs.utils.shp.ShpWriterUtil;

import java.io.File;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author Mr.superbeyone
 * @project export
 * @className ShpExportUtil
 * @description shp導出
 * @date 2019-09-19 15:59
 **/

public class ShpExportUtil {


    /**
     * @param filePath     文件存儲路徑
     * @param dataList     數據集
     * @param fields       字段集合
     * @param geomFieldKey 空間字段
     * @param charset      字符編碼
     * @param keyToUpper   字段名大小寫 小於0:轉大寫,=0:保持原格式 大於0: 轉大寫
     * @param removeKeySet 需要移除的 key 集合
     * @param addKeySet    需要添加的 key 集合
     * @return 路徑
     */
    public static File exportShpOfPoint(File filePath, List<Map<String, Object>> dataList, Set<String> fields, String geomFieldKey,
                                        Charset charset, int keyToUpper, Set<String> removeKeySet, Set<String> addKeySet) {
        return ShpWriterUtil.shpWriter(filePath, dataList, fields, ShpWriterUtil.POINT, geomFieldKey,
                charset, keyToUpper, removeKeySet, addKeySet);
    }

    /**
     * @param filePath     文件存儲路徑
     * @param dataList     數據集
     * @param fields       字段集合
     * @param geomFieldKey 空間字段
     * @param charset      字符編碼
     * @param keyToUpper   字段名大小寫 小於0:轉大寫,=0:保持原格式 大於0: 轉大寫
     * @param removeKeySet 需要移除的 key 集合
     * @param addKeySet    需要添加的 key 集合
     * @return 路徑
     */
    public static File exportShpOfLine(File filePath, List<Map<String, Object>> dataList, Set<String> fields, String geomFieldKey,
                                       Charset charset, int keyToUpper, Set<String> removeKeySet, Set<String> addKeySet) {
        return ShpWriterUtil.shpWriter(filePath, dataList, fields, ShpWriterUtil.LINE, geomFieldKey,
                charset, keyToUpper, removeKeySet, addKeySet);
    }

    /**
     * @param filePath     文件存儲路徑
     * @param dataList     數據集
     * @param fields       字段集合
     * @param geomFieldKey 空間字段
     * @param charset      字符編碼
     * @param keyToUpper   字段名大小寫 小於0:轉大寫,=0:保持原格式 大於0: 轉大寫
     * @param removeKeySet 需要移除的 key 集合
     * @param addKeySet    需要添加的 key 集合
     * @return 路徑
     */
    public static File exportShpOfPolygon(File filePath, List<Map<String, Object>> dataList, Set<String> fields, String geomFieldKey,
                                          Charset charset, int keyToUpper, Set<String> removeKeySet, Set<String> addKeySet) {
        return ShpWriterUtil.shpWriter(filePath, dataList, fields, ShpWriterUtil.POLYGON, geomFieldKey,
                charset, keyToUpper, removeKeySet, addKeySet);
    }

}

測試類

@SpringBootTest
@RunWith(SpringRunner.class)
public class ShapeExportTest {

    @Test
    public void testExportShape() {
       
        List<String> fields = //數據庫表字段集合,參見文末 查詢 PostgreSql 指定表的字段集合
        String selectFields = getSelectFields(fields);
        List<Map<String, Object>> dataList = //從數據庫中查詢到的數據集合
        //數據類型,0未知,1點,2線,3,面,4混合
        int dataType = 1; //需要導出的空間類型
        File filePath = new File("D:\\data\\shp\\" + System.currentTimeMillis());//shp文件要保存的文件路徑

        Set<String> fieldSet = new HashSet<>(fields);
        Set<String> removeKeySet = getRemoveKeySet();
        //數據類型,0未知,1點,2線,3,面,4混合
        switch (dataType) {
            case 1:
                ShpExportUtil.exportShpOfPoint(filePath, dataList, fieldSet, "你的空間字段", StandardCharsets.UTF_8, 0, removeKeySet, null);
                break;
            case 2:
                ShpExportUtil.exportShpOfLine(filePath, dataList, fieldSet, "你的空間字段", StandardCharsets.UTF_8, 0, removeKeySet, null);
                break;
            case 3:
                ShpExportUtil.exportShpOfPolygon(filePath, dataList, fieldSet, "你的空間字段", StandardCharsets.UTF_8, 0, removeKeySet, null);
                break;
            default:
                return;
        }

    }

    private Set<String> getRemoveKeySet() {
        Set<String> remove = new HashSet<>();
        remove.add("不需要導出的字段過濾");
        return remove;
    }

    private String getSelectFields(List<String> fieldList) {
        StringBuilder builder = new StringBuilder();
        for (String field : fieldList) {
            switch (field) {
                case "不需要導出的字段過濾":
                   continue;
                    
                case "你的空間字段":
                    builder.append("st_astext(")
                            .append("你的空間字段").append(") ")
                            .append("你的空間字段 別名")
                            .append(",");
                    continue;
                default:
                    builder.append(field).append(",");
            }
        }
        if (builder.toString().endsWith(",")) {
            builder.deleteCharAt(builder.lastIndexOf(","));
        }
        return builder.toString();
    }
}

查詢 PostgreSql 指定表的字段集合

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章