【python使用】使用python读取mid/mif文件,高精地图解析

MIF/MID格式简介

1.使用geopandas读取:

   df = geopandas.read_file(path, encoding='UTF-8')
   gdf = geopandas.GeoDataFrame(df, geometry='geometry', crs='+init=epsg:4326')

此方法简单。但是缺点较为明显,当文件较大时,会比较吃内存。

2.使用fiona读取:

  下面这个方法直接适应fiona去读取mid/mif,此方法读取速度与1相同。但是占内存小很多。  

  def parse_mif(path, columns=None, **config):
        """
        读取mid/mif,shp文件,该函数占用内存相较于read_mif少
        :param path: 文件所在路径
        :param columns: mif文件所需要的列
        :param config: 配置,例如 编码
        :return:
        """
     
        import fiona
        from shapely.geometry import shape
     
        with fiona.open(path, **config) as features:
            crs = features.crs
            record_list = []
            logging.info("start")
            for line in features:
                if columns is None:
                    d = {'geometry': shape(line['geometry']) if line['geometry'] else None}
                    d.update(line['properties'])
                    record_list.append(d)
                else:
                    d = {'geometry': shape(line['geometry']) if line['geometry'] else None}
                    for col in columns:
                        d[col] = line['properties'][col]
                    record_list.append(d)
     
            logging.info("end")
            columns = columns + ["geometry"] if columns is not None else list(features.meta["schema"]["properties"]) + [
                "geometry"]
            gdf = gpn.GeoDataFrame(record_list, columns=columns)
            gdf.crs = crs
            return gdf
     
        return gpn.GeoDataFrame()

GDAL读取midmif文件(python版)

在工作中,需要经常跟midmif文件打交道,并且经常都是批量处理,虽然mapinfo工具也可以做到,但是公司没有购买版权,只有寻求它法。
作为一个产品PM,对技术不怎么精通,对python也不熟悉,但是产品语言和技术语言都是相通的,于是工作之余学习研究了一段时间,现在的水平基本可以处理一些基本的业务和产品逻辑需求。把自己的学习小成果总结下,方便入门gdal的同学,更多的是梳理下知识。
读取midmif文件

读取midmif文件步骤:
1、创建驱动;
2、创建datasource;
3、遍历datasource中的layer;
4、获取layer的属性;
5、获取feature的值。
实现代码:
 

driver = ogr.GetDriverByName("MapInfo File")
#datapath是mif文件所在的目录
ds = driver.Open(datapath)
#遍历datasource中的内容
for layer in ds:
        #获取每一个layer的名称
        layer_name = in_layer.GetName()
        print(layer_name)
        #获取layer的属性定义
        layer_defn = layer.GetLayerDefn()
        #遍历layer下的feature
       for field_index in range(0, layer_defn.GetFieldCount()):
             #获取每一个layer中的field定义
           oField =layer_defn.GetFieldDefn(field_index)
           #输出每一个属性的名称,属性类型,属性长度,属性精度
           print( '%s: %s(%d.%d)' % (oField.GetNameRef(),oField.GetFieldTypeName(oField.GetType()),oField.GetWidth(),oField.GetPrecision()))
         #遍历图层中的要素
         #遍历图层中的要素,遍历方式1:
        feature = layer.GetNextFeature()
        while feature is not None:  
            # 获取要素中的属性表内容  
            for index in range(layer_defn.GetFieldCount()):  
                oField =layer_defn.GetFieldDefn(index)  
                line =  " %s (%s) = " % (oField.GetNameRef(),oField.GetFieldTypeName(oField.GetType()))  
                if feature.IsFieldSet(index):  
                    line = line+ "%s" % (feature.GetFieldAsString(index))  
                else:  
                    line = line+ "(null)"  
                print(line)  
            # 获取要素中的几何体  
            geometry =feature.GetGeometryRef()  
            print(geometry)
            # 演示,只输出一个要素信息  
            break
        #遍历图层中的要素,遍历方式2:
        for feature in layer:
            #根据不同layer,获取相应的字段值
            if layer_name == 'PlateRes_Manoeuvreanhui':
                #获取相应的字段的值
                group_id = feature.GetField("Group_ID")
                print(group_id)
                #满足条件时,更新相应的字段值,这里可以批量更新某些字段的值
                if group_id == '3122685':
                   feature.SetField("Datetype", '22')      
            #演示,输出一个要素信息  
            break
        feature.Destroy()

## 完整的代码如下:
#python代码
import os,sys
from osgeo import gdal
from osgeo import ogr
from osgeo import osr

#读取mif文件
def readmif(file_path):
    #为了支持中文路径
    gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8","NO")  
    #为了使属性表字段支持中文
    gdal.SetConfigOption("SHAPE_ENCODING","")  
    #注册所有的驱动
    ogr.RegisterAll()
    #创建mif类型文件驱动
    driver = ogr.GetDriverByName('MapInfo File')
    print(file_path)
    ds = driver.Open(file_path)
    for layer in ds:
        layer_name = layer.GetName()
        print(layer_name)
        layer_defn = layer.GetLayerDefn()
        for field_index in range(0, layer_defn.GetFieldCount()):
           #获取每一个layer中的field定义
           field_defn = layer_defn.GetFieldDefn(field_index)
           #获取属性定义
           oField =layer_defn.GetFieldDefn(field_index)
           #输出每一个属性的名称,属性类型,属性长度,属性精度
           print( '%s: %s(%d.%d)' % (oField.GetNameRef(),oField.GetFieldTypeName(oField.GetType()),oField.GetWidth(),oField.GetPrecision()))
        #遍历图层中的要素,遍历方式1:
        feature = layer.GetNextFeature()
        while feature is not None:  
            # 获取要素中的属性表内容  
            for index in range(layer_defn.GetFieldCount()):  
                oField =layer_defn.GetFieldDefn(index)  
                line =  " %s (%s) = " % (oField.GetNameRef(),oField.GetFieldTypeName(oField.GetType()))  
                if feature.IsFieldSet(index):  
                    line = line+ "%s" % (feature.GetFieldAsString(index))  
                else:  
                    line = line+ "(null)"  
                print(line)  
            # 获取要素中的几何体  
            geometry =feature.GetGeometryRef()  
            print(geometry)
            # 为了演示,只输出一个要素信息  
            break
        #遍历图层中的要素,遍历方式2:
        for feature in layer:
            if layer_name == 'PlateRes_Manoeuvreanhui':
                data_field = feature.GetField("Group_ID")
                print(data_field)
            break
        feature.Destroy()
    ds.Destroy()
    
def main():
    file_path = sys.argv[1]
    readmif(file_path)

    
if __name__ == "__main__":
    main()

`
MIF/MID格式简介

MapInfo MIF/MID文件格式描述

        这种通用的格式允许把普通的数据添加到多种的图像元素中。MIF/MID文件采用ASCII编码,因此它是可编辑的、相对比较容易生成、并且可以工作在MapInfo支持的所有平台上。也许理解MIF格式的最好的方法是在读完这篇文章后,拿着MIF格式说明,研究一个MIF文件。你也可以通过“exporting files to MIF”创建你自己的MIF文件,然后在文本编辑器中好好的研究它。

        MapInfo数据存在于两种文件中--图形数据存储在.MIF文件、文本数据存储在.MID文件。文本数据包括每一项记录的一行和回车,回车加换行,行之间的换行。MIF文件的数据包括两部分--文件头和数据区。文件头存放着如何创建MapInfo表格的信息;数据区存放着图形对象的解释。

        下面是MIF文件头的描述(包括可选项,下表中由“[ ]”括起来的部分就是可选项)。

    Version n
     
    Charset "characterSetName"
     
    [ DELIMITER "<c>" ]
     
    [ UNIQUE n,n.. ]
     
    [ INDEX n,n.. ]
     
    [ COORDSYS... ]
     
    [ TRANSFORM... ]
     
    COLUMNS n
     
    <name> <type>
     
    <name> <type>
     
    …
     
    …
     
    DATA
     

1.Version 版本号

“Version”说明你使用的MIF格式的版本(VERSION 1, VERSION 2, VERSION 300中的一种)。Version 300,引自Mapinfo 3.0,允许形容由多段组成的折线对象。

2.Charset 字符集

“Charset”指定表中创建文本所使用的字符集。比如说:"WindowsLatin1"说明文件使用的是the Windows US & Western Europe字符集;"MacRoman"说明文件使用的是the Macintosh US & Western Europe字符集;或者,注明"Neutral"是为了防止将文本转成了另外的字符集。如果你没有使用其中任何一个字符集,你可以通过exporting a table和examining the .MIF file in a text editor为你的字符集指定正确的语法。

3.Delimiter 分隔符

指定引号(即""或者'')之间的分隔符,比如说:

DELIMITER ";"

默认的分隔符是Tab;如果你使用的是默认分隔符,你不需要“DELIMITER”这一行。

4.Unique

指定一个数字。这个数字指定一个数据库的列;3是第三列,7是第七列,以此类推。发生在UNIQUE指定的列上的事情是微妙的。比如说,想象一下你建立一个高速公路的数据库。每一条路都只有一个名字,但是在每一路段中都会把名字重写一遍。这时你会把NAME这一列放在一个单独的表中,而包含每个路段的信息的其他列不会放在那个表中。这样就可以创建两个相关的表格:一个NAME表,一个包含其他信息。This is how MapInfo's various street maps(StreetInfo) are prepared.

5.Index 索引

“Index”指明表中已经建立索引的列,“INDEX”项包括一个数字(或者一系列数字)。每一个数字指定一个数据库的列;3是第三列,7是第七列,以此类推。在“INDEX”表中指定的列会建立索引。

6.CoordSys

指定“COORDSYS”项表示数据不是以经纬度的形式存储的。当没有指定“COORDSYS”这一项时,数据被认为是以经纬度的方式存储。All coordinates are stored with respectto the northeast quadrant.。 在美国的点的x坐标为负而在欧洲的点(Greenwich以东)的坐标为正。在北半球的点的y坐标为正而在南半球的点的坐标为负。

7.Transform 转换

你可以通过“Transform”实现地理元素的坐标转换。

--------------------------------------------

| Quadrant 2: | Quadrant 1: |

| Nortwest Quadrant | Norteast Quadrant |

--------------------------------------------

| Quadrant 3: | Quadrant 4: |

| Southwest Quadrant | Southeast Quadrant |

--------------------------------------------

8.Columns 列

指定列数。然后,为每一列,建立一行(包括the column name、the column type、一个用来指定域长度的数字--仅为character和decimal类型的列建立)用来说明其格式。有效的列类型包括:

char(width)

integer        [说明:which is 4 bytes, from -2^31 to 2^31-1]

smallint        [说明:which is 2 bytes, so it can only store numbers between -32767 and +32767)]

decimal (width, decimals)

float

date

logical

下面是mif文件头的COLUMNS部分的一个例子:

STATE char (15)

POPULATION integer

AREA decimal (8,4)

通过上面指定的数据库,我们知道对应的MID文件有三列:

列名            列类型

STATE           char(15) 15位长的字符串

POPULATION     INTGER   整型

AREA            decimal(8,4) 一个最长8位、小数点后有4位的小数

MIF文件的“data”部分紧跟着文件头并且必须由一个单行“DATA”引出:

DATA

MIF文件的数据部分可以包括任意长度的图形变量,其中每一项对映着一个图形对象。MapInfo自动使MIF和MID文件里面的每一条相一致,比如说:MIF文件的第一个object对应着MID文件的第一行,MIF文件的第二个object对应着MID文件的第二行。

当MIF文件中没有图形对象与MID文件的行对应时,一个“blank”对象必须写在MIF文件中相应的位置。

NONE

图形对象可以被指定为如下几种类型:

point          //点

line           //线

polyline       //折线

region         //区域

arc            //弧

text           //文本

rectangle      //矩形

rounded rectangle   //圆矩(即4个角做“钝化”处理的矩形)

ellipse        //椭圆

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: 有多种方法可以使用Python读取mif文件。一种方法是使用fiona库,可以直接适应fiona去读取mid/mif文件。这种方法的优点是读取速度快且占用内存较少。可以使用parse_mif函数来读取mif文件,该函数可以指定需要读取的列,并可以配置编码等参数。函数内部使用了fiona库和shapely库来处理文件和几何数据。最后返回一个GeoDataFrame对象,其中包含了读取的数据和几何信息。\[2\] 另一种方法是使用geopandas库来读取mif文件。可以使用geopandas的read_file函数来读取mif文件,可以指定编码等参数。读取后可以将结果转换为GeoDataFrame对象,其中包含了读取的数据和几何信息。\[3\] 以上是两种常用的方法,根据具体需求选择适合的方法来读取mif文件。 #### 引用[.reference_title] - *1* [GDAL读取midmif文件python版)](https://blog.csdn.net/u011210523/article/details/95808300)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [使用python读取mid/mif文件](https://blog.csdn.net/MoseSky/article/details/88861823)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值