mid、mif文件转shapefile、geojson等格式的数据

32 篇文章 45 订阅

mif/mid文件说明

mid、mif文件是Mapinfo用来存储空间数据的一种格式,mif文件保存了地图的属性表结构和空间信息(点、线、面),mid文件则按照mif文件里表结构的顺序在每行保存了各个字段的属性信息,具体介绍可以参考这篇博文

https://ershi.blog.csdn.net/article/details/99696139

mid、mif文件如何转成我们常见的shapefile、geojson等格式的数据

下面的方法,其中包括转wkt、geometry、SimpleFeature等格式的都可以作为参考(以线数据为例),直接上代码

需要注意的是:DataUtilities.createType方法创建要素时,String类型的字段长度默认是254,如果字段很多和要素也很多,dbf文件会比正常变大很多,如果需要自定义String类型长度,可以看一下DataUtilities类源码,重写一下;

    private void roadMidMiftoShp(String path,String mid,String mif){
        //List<LineString> lineList = new ArrayList<>();
        List<List<String>> midRows = loadMidFile(new File(mid));
        logger.info("加载mid结束");
        List<String> colField = new ArrayList<>();
        Map<Integer, List<List<Double>>> lineRows = new HashMap<>();
        loadMifFile(new File(mif),true,colField,lineRows);
        logger.info("加载mif结束");
        List<SimpleFeature> lineFeatures = new ArrayList<>();
        String typeSpec = "the_geom:LineString:srid=4326";
        for (String col : colField){
            typeSpec = typeSpec + "," + col + ":String";
        }
        try {
            SimpleFeatureType featureType = DataUtilities.createType("dsline",typeSpec);
            SimpleFeatureBuilder linefeatureBuilder = new SimpleFeatureBuilder(featureType);
            for (int i = 0; i < midRows.size(); i++){
                for (int j = 0; j < colField.size(); j++){
                   linefeatureBuilder.set(colField.get(j),midRows.get(i).get(j));
                }
                SimpleFeature featureLine = linefeatureBuilder.buildFeature(String.valueOf(i));
                String lineStr = "LINESTRING(";
                List<List<Double>> lineRow = lineRows.get(i);
                for (List<Double> line : lineRow){
                    lineStr = lineStr + line.get(0) + " " + line.get(1) + ",";
                }
                lineStr = lineStr.substring(0,lineStr.length()-1) + ")";
                LineString roadLine = createLineByWKT(lineStr);
                featureLine.setDefaultGeometry(roadLine);
                lineFeatures.add(featureLine);
            }
//            List<Geometry> geometryList = featuresToGeometrys(lineFeatures);
//            lineList = toSimpleLine(geometryList);
        }catch (Exception e){
            logger.error("roadMidMiftoLine异常:", e);
        }
        String lineFile = path + File.separator  + "line.shp";
        String lineJson = path + File.separator  + "line.geojson";
        featureToGeojson(lineJson , lineFeatures);
        featureToShp(lineFile , lineFeatures);
        logger.info("转换shp结束");
    }

    
    public List<List<String>> loadMidFile(File file) {
        List<List<String>> midRows= new ArrayList<>();
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "gbk"));
            String line;
            while ((line = reader.readLine()) != null) {
                List<String> cols = Arrays.asList(line.split(",",-1));
                if (cols.size() > 0) {
                    for (int i = 0; i < cols.size(); i++) {
                        String value = cols.get(i).replace("\"", "");
                        cols.set(i, value);
                    }
                    midRows.add(cols);
                }
            }
            reader.close();
        } catch (FileNotFoundException e) {
            logger.error("loadMidFile():", e);
        } catch (IOException e) {
            logger.error("loadMidFile():", e);
        }
        return midRows;
    }

    public void loadMifFile(File file, Boolean isLoadMifData,List<String> colField,Map<Integer, List<List<Double>>> lineRows) {
        //colField 为mid文件里各个值对应的字段
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "gbk"));
            String line;
            while ((line = reader.readLine()) != null) {
                if (line.toUpperCase().startsWith("COLUMNS")) {
                    int num = Integer.parseInt(line.substring("Columns ".length()));
                    for (int i = 0; i < num; i++) {
                        line = reader.readLine().trim();
                        List<String> cols = Arrays.asList(line.split(","));
                        if (cols.size() > 0) {
                            colField.add(cols.get(0).split(" ")[0].trim());
                        }
                    }
                    if (isLoadMifData) {
                        //装载mif里的geo数据(点,线,面不同类型)
                        loadMifFileGeoDatas(reader,lineRows);
                    }
                    break;
                }
            }
            reader.close();
        } catch (Exception e) {
            logger.error("loadMifFile():", e);
        }

    }

    //如果geo数据为线
    public void loadMifFileGeoDatas(BufferedReader reader,Map<Integer, List<List<Double>>> lineRows)  {
        Integer rowIndex = -1;
        try {
            String line;
            while ((line = reader.readLine()) != null) {
                List<List<Double>> lines = new ArrayList<>();
                line = line.trim();
                if (line.toUpperCase().contains("NONE")){
                    lineRows.put(++rowIndex, lines);
                }
                if (line.toUpperCase().startsWith("LINE")) {
                    List<String> point = Arrays.asList(line.split(" "));
                    if (point.size() == 5) {
                        List<Double> point1 = new ArrayList<>();
                        point1.add(Double.parseDouble(point.get(1)));
                        point1.add(Double.parseDouble(point.get(2)));
                        lines.add(point1);

                        List<Double> point2 = new ArrayList<>();
                        point2.add(Double.parseDouble(point.get(3)));
                        point2.add(Double.parseDouble(point.get(4)));
                        lines.add(point2);
                    }
                    lineRows.put(++rowIndex, lines);
                }
                if (line.startsWith("Pline")) {
                    int num = Integer.parseInt(line.substring("Pline ".length()));
                    for (int i = 0; i < num; i++) {
                        line = reader.readLine().trim();
                        List<String> point = Arrays.asList(line.split(" "));
                        if (point.size() == 2) {
                            List<Double> points = new ArrayList<>();
                            points.add(Double.parseDouble(point.get(0)));
                            points.add(Double.parseDouble(point.get(1)));
                            lines.add(points);
                        }
                    }
                    lineRows.put(++rowIndex, lines);
                }
            }
            reader.close();
        } catch (Exception e) {
            logger.error("loadMifFileGeoDatas():", e);
        }
    }

    public LinkedHashMap<String, Object> getGeometryMap(Map<Integer, List<List<Double>>> lineRows,Integer rowIdx) {
        if (lineRows!= null) {
            List<List<Double>> line = lineRows.getOrDefault(rowIdx, null);
            LinkedHashMap<String, Object> geometryMap = new LinkedHashMap<String, Object>() {{
                put("type", "LineString");
                put("coordinates", line);
            }};
            return geometryMap;
        }
        return null;
    }

    
    public LineString createLineByWKT(String lineStr) throws ParseException {
        GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory(null);
        WKTReader reader = new WKTReader( geometryFactory );
        LineString line = (LineString) reader.read(lineStr);
        return line;
    }

    public void featureToShp(String path, List<SimpleFeature> outFeatures){
        try {
            FileDataStoreFactorySpi factory = new ShapefileDataStoreFactory();
            File file = new File(path);
            if (file.exists()) {
                return;
            }
            Map map = Collections.singletonMap("url", file.toURI().toURL());
            ShapefileDataStore dataStore = (ShapefileDataStore)factory.createNewDataStore(map);
            SimpleFeatureType featureType =outFeatures.get(0).getType();
            dataStore.createSchema(featureType);
            dataStore.forceSchemaCRS(CRS.decode("EPSG:4326"));
            Transaction transaction = new DefaultTransaction("create");
            String typeName = dataStore.getTypeNames()[0];
            SimpleFeatureSource featureSource = dataStore.getFeatureSource(typeName);
            if (featureSource instanceof SimpleFeatureStore) {
                SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;
                SimpleFeatureCollection collection = new ListFeatureCollection(featureType, outFeatures);
                featureStore.setTransaction(transaction);
                try {
                    featureStore.addFeatures(collection);
                    transaction.commit();
                } catch (Exception problem) {
                    problem.printStackTrace();
                    transaction.rollback();
                } finally {
                    transaction.close();
                }
            } else {
                logger.info(typeName + " does not support read/write access");
            }
        }catch (Exception e){
            logger.error("featureToShp异常:",e);
        }
    }

    public static void featureToGeojson(String path, List<SimpleFeature> outFeatures){
        Writer gjsonWriter = null;
        try{
            File file = new File(singleRoadPath);
            if (file.exists()) {
                file.delete();
            }
            if (outFeatures.isEmpty()) {
                return;
            }
            FeatureJSON featureJSON = new FeatureJSON(new GeometryJSON(6));
            gjsonWriter = new OutputStreamWriter(new FileOutputStream(singleRoadPath), StandardCharsets.UTF_8);
            featureJSON.writeFeatureCollection(new ListFeatureCollection(outFeatures.get(0).getType(), outFeatures), gjsonWriter);

        }catch (Exception e){
            logger.error("feature写入异常:" + e);
        }finally {
            try{
                if (gjsonWriter != null) {
                    gjsonWriter.flush();
                    gjsonWriter.close();
                }
            }catch (IOException ie){
                logger.error("流关闭异常:" + ie);
            }
        }
    }
    
    public static List<LineString> toSimpleLine(List<? extends Geometry> geometryList) {
        List<LineString> simpleLineList = new ArrayList<>();
        for (Geometry geometry : geometryList) {
            if (geometry instanceof MultiLineString) {
                for (int j = 0; j < geometry.getNumGeometries(); j += 1) {
                    simpleLineList.add((LineString) geometry.getGeometryN(j));
                }
            } else if (geometry instanceof LineString) {
                simpleLineList.add((LineString) geometry);
            }
        }
        return simpleLineList;
    }

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二十同学

谢谢大佬打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值