OGR库读写mif/tab文件lonefox使用经验小结

来源:互联网 发布:数据库架构师 北京 编辑:程序博客网 时间:2024/05/16 14:00

 ===================================

本人log中所有未注明转载的文章和blog一般为本人原创或整理加工,
原创文章版权本人(lonefox)所有;转载文章版权归原作者所有;

http://blog.csdn.net/boythl

欢迎转载,但请注明出处,保留作者和版权信息。

===================================

  

最近项目中使用GDAL/OGR库读写mif和tab文件, 经过几天的折腾,积累了点点经验,且记之.

 

1. OGRSFDriverRegistrar::Open(Path, FALSE);只能读文件

对于OGRSFDriverRegistrar::Open方法, ogr内置的mif/TAB读写库MITAB是不支持该方法的更新的,看下面的MITAB源码:

  再深入源码,你会发现,通过Open方法传给IMapInfoFile类访问文件的方式是TABRead,而非TABWrite

  也许你会说"这是OGRTABDriver的方法, 可以看看OGRMIFDriver的方法?", 遗憾, 我们只能用 RegisterOGRTAB(); 注册mif和tab通用的驱动,RegisterOGRMIF();是一个只有定义而没有函数实现的美丽谎言, 不知道OGR库留着这个定义的目的何在。也不存在OGRMIFDriver,OGRTABDriver通吃mif和tab文件。这也是我们的第二点。

 

2.只使用RegisterOGRTAB();注册tab/MIF文件读写驱动

原因上面已经提过。单凭RegisterOGRTAB();已足够。

mif和tab文件的读取都是通过Open方法,MITAB库内部会调用SmartOpen方法区分是mif/mid后缀或是tab后缀。

 

3.写mif/tab文件的方法

OGRSFDriver *pDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName("MapInfo File");
OGRDataSource *pDSTAB = pDriver->CreateDataSource(strTabPath);//创建一个文件,根据扩展名自动判断是创建mif文件或tab文件

lonefox的解释: MITAB库在实现CreateDataSource方法时会调用OGRTABDataSource的Create方法,而非Open方法

Create方法内部会调用IMapInfoFile类的Open方法,但区别在于访问模式参数传递的是"wb"!

而该模式将标记 m_eAccessMode = TABWrite; 不是OGRDataSource::Open方法对应的TABRead模式;

顺带提句,IMapInfoFile内只有TABWrite和TABRead, 是不能又读又写的

 

4.读写mif/tab的方法

如果我一个文件已有部分数据,但我想打开后继续加数据,怎么办?

我采取一种曲线救国的方法解决该问题: i. 打开该文件; ii.按上面第三条的方法新建一个临时文件供写入; iii. 使用OGRDataSource类的CopyLayer方法将 i 中打开的旧数据贴进新layer,iv. 调用OGRLayer::SyncToDisk方法保存新文件;v. 删除旧文件将临时文件更名

若有大侠有更好的方法,一定要不吝指教才好!!!

 

5. mif/tab格式互转

利用OGRDataSource::CopyLayer,mif和tab格式的互转就再简单不过了。直接源码吧

tab转mif和上面代码雷同,略之。

 

6. ogr库的bug

6.1. 读取空mif文件失败的限制

如果一个mif文件是空文件(当然,文件格式是符合mif格式的,只是图层中没有feature),即mid文件尺寸为0;那么,ogr的open方法会返回NULL,意味着读取失败。

这是因为MITAB库在打开mid文件时会尝试读一行

这段代码位于int MIFFile::Open(const char *pszFname, const char *pszAccess, GBool bTestOpenNoError /*=FALSE*/ )方法内部。

有两种方法解决该问题: 1. 修改ogr库源码,先前我们是这么干的;2. 打开前向空mid文件插入一个换行符,该字符的存在能“欺骗”上文GetLine方法不返回NULL

 

6.2. 字符集的限制

ogr写出的mif/tab文件,字符集全部都是Neutral,根本不管先前的charset,鄙人驽钝,未发现修改字符集的方法,有大虾知道的话请千万要不吝指教啊!

但在IMapInfoFile类中存在一个SetCharset接口,该方法由IMapInfoFile默认实现,未被override;且该方法在MITAB库内部未被调用。

问题是OGR库未提供类似接口。

解决方法: 1. 修改ogr库,增加一个设置charset的接口。2. 抛弃OGR库,直接使用IMapInfoFile类操纵mif文件

 

6.3. 只支持少量sql查询,不支持空间查询

sql查询的相关内容可以看swq.h文件; 空间查询在OGR1.60版还未看到接口,期待。

 

7. 尽量使用GetNextFeature代替GetFeatureCount

我们看看OGRLayer::GetFeatureCount方法的实现代码

由上可以看到,大部分情况下,GetFeatureCount的参数取False时将直接得到-1;如果采用TRUE,不好意思,就是一次整图层所有feature的遍历。

很遗憾的是,MITAB库并未override该方法,也就没有更高效的算法了。

因此, 如果想判断图层是否有feature,例如sql查询的查询结果是否为空,不明确要求得到要素个数时,请先使用ResetReading再判断GetNextFeature是否为NULL,避免使用GetFeatureCount。

切记,OGR的GetFeatureCount不同于ado库的GetRecordCount。

 

    时间匆忙,lonefox上班间隙随手写就,再加就几天的使用,经验有限,错误之处恳请斧正;另,GIS同行欢迎加好友共同探讨!

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 金立手机微信语音播放失败怎么办 手机4g网络变2g怎么办 生存战争2吃了腐烂的食物后怎么办 古筝调音 d的显示为b怎么办 消防建审没有原有的结构图纸怎么办 生石灰弄到脸上用水洗后发热怎么办 吃了没熟的鹅肝怎么办 蹲式厕所被袜子堵了怎么办 自热包的水喝了怎么办 火锅发热包不小心吃了怎么办 塑料螺旋饭盒盖子被吸住了怎么办 昨晚喝太多酒今天排尿拍不出怎么办 开光过的貔貅摔坏一点嘴巴怎么办 诺基亚6第二代忘记解屏密码怎么办 工厂搬迁已经般空了工人怎么办 被上司强行换了一个岗位该怎么办 上司要调整我岗位我该怎么办 我被别人打伤了警察不管怎么办 郑州共享汽车小黄车路上坏了怎么办 爱跟别人聊朋友的事怎么办 任职履历上学历写错了怎么办 六个月的宝宝老长婴儿湿疹怎么办 入伍前驾照没考完退伍后过期怎么办 在电脑上玩英雄联盟没有声音怎么办 梦幻西游新区抢不到副本积分怎么办 倒车时遇上机动车碰瓷的怎么办 电瓶车相撞对方全责但不赔偿怎么办 轻微刮蹭逃逸对方想多要钱怎么办 正常开车撞伤了闯红灯的人怎么办 发现小事故要保持现场堵车怎么办 私处刮毛外面皮肤不小心弄伤怎么办 老婆骂孩子不准老公带饿小孩怎么办 结婚3年妻子不让丈夫碰怎么办 老婆出轨现在没证据他要离婚怎么办 结婚后老婆不让碰分房睡离婚怎么办 电动车调速把手变速挡坏了怎么办 路边车辆贴条了超过15天了怎么办 违停交警拍照了没贴条 照片怎么办 支付宝违章缴费罚单输错了怎么办 交警查酒驾跑了把警车撞了怎么办 禁止进入待行区的时候进入了怎么办