爱气象,爱气象家园! 

气象家园

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

搜索
查看: 7927|回复: 11

[分享资料] 将文本文档转换成二进制格式时recl 的设置问题

[复制链接]

新浪微博达人勋

发表于 2011-12-6 00:32:46 | 显示全部楼层 |阅读模式

登录后查看更多精彩内容~

您需要 登录 才可以下载或查看,没有帐号?立即注册 新浪微博登陆

x
这个问题是我回复帖子:grads只有横轴,没有纵轴http://bbs.06climate.com/forum.php?mod=viewthread&tid=4834&fromuid=1644 (蓝色字体的内容来自该贴)中发现的。虽然在回复中提到了这个问题,但是没有人回复我,在这里我自己发个帖子问问吧!
这是1951年到2010年某个站点的每年降水
149 59 80 336 40 158 97 140 73 222 125 147 109 133 202 48 88 189 225 362 151 76 146  62 57 162 258 135 144 113 109 145 256 170  69 133 135 108 181  31 472 119 231  62  93 313 206  85 219 180 119 162 234 273 122  47 149 244  44  213
我将以上的存放以上数据的文件命名为luntan.txt中,以下是我将txt文件转换成二进制格式的fortran程序,我的问题是:为什么当我设置记录长度recl=1的时候写出来的grd文件,我用'set gxout print'查看数据的时候除了第一个数据以外其他的59数据都是0,而设成recl=60的时候就正常。而之前在论坛上一种经典的设置是:recl=ix*iy ,其中ix和iy分别代表x和y方向上的格点数,而不用管时间维和高度维是否固定,所以我的这种情况不就相当于recl=1(1*1),而时间维为60吗?
还请大家为我指点指点。

program main
implicit none
real::rain(60)
integer::i,irec
open(15,file='f:/data/test/luntan.txt')
read(15,*)(rain(i),i=1,60)
print*,(rain(i),i=1,60)
open(16,file='f:/data/test/luntan.grd',form='binary',recl=60)
irec=1
write(16,rec=irec)(rain(i),i=1,60)
!do i=1,60
!write(16,rec=irec)rain(i)
!irec=irec+1
!enddo
close(15)
close(16)
end
密码修改失败请联系微信:mofangbao

新浪微博达人勋

 成长值: 19710
发表于 2011-12-6 01:16:34 | 显示全部楼层
你可能设置recl=1的时候没把数据写进去,你这问题还不够具体,就是recl=1的情况还有gs,提示之类的都没给出,很难判断的~
密码修改失败请联系微信:mofangbao

新浪微博达人勋

 成长值: 0
发表于 2011-12-6 08:30:53 | 显示全部楼层
根据fortran的file里面有介绍说recl实际上指的是数据记录的位置,我理解类似于nc里面的直接读取,比如写的时候标记了recl为100,表示这一个file里面有100个文件记录,需要第50个的时候,用grads提取时,直接可以跳过前面49个跳到第50。不知道我理解的对否,还请多多直接,对于fortran中txt 2 grd还真是一窍不通,惭愧
密码修改失败请联系微信:mofangbao

新浪微博达人勋

 成长值: 19710
发表于 2011-12-6 08:45:11 | 显示全部楼层
@言深深有空我教你,不过得。。。。
密码修改失败请联系微信:mofangbao

新浪微博达人勋

 成长值: 0
发表于 2011-12-6 08:56:36 | 显示全部楼层
密码修改失败请联系微信:mofangbao

新浪微博达人勋

0
早起挑战累计收入
发表于 2011-12-6 09:07:57 | 显示全部楼层
我猜楼主是把open的recl改成了1,然后在用你注释掉的那几行来输出文件,看上去很没有问题!不过...再看看你打开文件的方式吧,豁然开朗了,原因就是fortran中默认打开文件是顺序读写的,而使用recl这个参数应该是form='unformatted' access='direct'中进行。楼主是CVF的编译器吧,如果是4.0的你这么写就直接编译失败了。修改楼主的代码如下:
..........
open(16,file='rain.grd',status='replace',form='unformatted',access='direct',recl=1)
irec=1
!write(16,rec=irec)rain
do i=1,60
write(16,rec=i)rain(i)
enddo
close(15)
close(16)
end
应该就没有问题了
看楼主原来没有注释的那部分:
rec的取值应该根据recl的数值来进行定义,recl的作用就是告诉编译器,这次写入的数据要放到那一个区块,因为一个recl占4个byte,也就是要写入的一个浮点数据,如果recl=60的时候,这次写入可用的就是60*4byte,当你在下面使用隐循环来写入数据的时候,fortran会始终在这个区块中进行操作,因此你的如下语句:
irec=1
write(16,rec=irec)(rain(i),i=1,60)
说明了是在文件的第一个 60*4byte区内来进行写入数据,使用内循环写入60次,每次4个byte,刚好是你60年的数据。其实在这里你的循环是多余的,可以用下面的写法代替:
irec=1
write(16,rec=irec)rain
关键问题出在你的open参数不对,如果你想用binary参数,应该这么写:
open(16,file='rain.grd',status='replace',form='binary')
write(16)rain
close(16)

我习惯用的是不带rec的一种写法,简洁明了

密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2011-12-6 12:36:54 | 显示全部楼层
本帖最后由 godenflame135 于 2011-12-6 12:41 编辑

坛主说得好!win下recl=1就是4个字节,linux下recl=1就是1个字节。楼主写recl=60,用隐式循环就是把4*60个字节写入了。更好的就是坛主说的那样,按照binary打开,write 一个数组名就一下把该数组所有的数据都写入了。
密码修改失败请联系微信:mofangbao

新浪微博达人勋

 楼主| 发表于 2011-12-7 14:21:59 | 显示全部楼层
呵呵,谢谢各位!受益匪浅啊!
密码修改失败请联系微信:mofangbao

新浪微博达人勋

 楼主| 发表于 2011-12-7 14:23:09 | 显示全部楼层
mofangbao 发表于 2011-12-6 09:07
我猜楼主是把open的recl改成了1,然后在用你注释掉的那几行来输出文件,看上去很没有问题!不过...再看看你 ...

谢谢,清风,我刚试了试,确如你所言。
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2012-4-12 15:47:32 | 显示全部楼层
冬日情愫+ 发表于 2011-12-7 14:21
呵呵,谢谢各位!受益匪浅啊!

请问版主,这样转换后二进制的数据怎么写ctl 呢!不太明白请教!
密码修改失败请联系微信:mofangbao
您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆

本版积分规则

Copyright ©2011-2014 bbs.06climate.com All Rights Reserved.  Powered by Discuz! (京ICP-10201084)

本站信息均由会员发表,不代表气象家园立场,禁止在本站发表与国家法律相抵触言论

快速回复 返回顶部 返回列表