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 //椭圆