||
$ bctot 2021 161 brdc1610.21n tbrdc1.161
STATUS :210621:1732:31.0 BCTOT/orbits/bctot: Started BCTOT ver. 10.15 2020/02/3 17:00:00 UTC (Linux) Library ver. 11.34 of 2020/03/17 20:40 UTC (Linux)
STATUS :210621:1732:31.0 BCTOT/orbits/openb: Opened print file: (Name bctot.out)
STATUS :210621:1732:31.0 BCTOT/orbits/openb: Opened output T-file: (Name tbrdce.161)
STATUS :210621:1732:31.0 BCTOT/orbits/openb: Opened input navigation file: (Name brdc1610.21n)
STATUS :210621:1732:31.0 BCTOT/bctot: Opened session.info
STATUS :210621:1732:31.0 BCTOT/orbits/bctot: Successfully read broadcast navigation file: (Name brdc1610.21n)
WARNING:210621:1732:31.0 BCTOT/orbits/bctot: No X-file, using all satellites on the nav-file
STATUS :210621:1732:31.0 BCTOT/orbits/bctot: Earth-fixed T-file tbrdce.161 being created
STATUS :210621:1732:31.0 BCTOT/orbits/bctot: Successfully wrote earth-fixed T-file: (Name tbrdce.161)
STATUS :210621:1732:31.0 BCTOT/orbits/openb: Opened print file: (Name trot.out)
STATUS :210621:1732:31.0 BCTOT/orbits/openb: Opened output T-file: (Name tbrdc1.161)
STATUS :210621:1732:31.0 BCTOT/orbits/openb: Opened input T-file: (Name tbrdce.161)
STATUS :210621:1732:31.0 BCTOT/orbits/trot: Input T-file is Earth-fixed, converting to inertial
At line 140 of file thdred.f (unit = 16, file = 'tbrdce.161')
Fortran runtime error: I/O past end of record on unformatted file
Error termination. Backtrace:
#0 0x7fd6c74dbea7 in ???
#1 0x7fd6c74dca45 in ???
#2 0x7fd6c74dd1fc in ???
#3 0x7fd6c75acb60 in ???
#4 0x7fd6c7c1baa5 in ???
#5 0x7fd6c7c0e6be in ???
#6 0x7fd6c7c0763d in ???
#7 0x7fd6c7c014b5 in ???
#8 0x7fd6c6d41b96 in ???
#9 0x7fd6c7c01509 in ???
#10 0xffffffffffffffff in ???
上面, 显示错误发生在thdred.f函数中,打开/opt/gamit10.71/gamit/lib/thdred.f查看140行代码:
read(iut) comt,nsat,nintrs, (satnam(isat),(tsatic(i,isat),i=1,nics),isat=1,nsat)
发现在读取T-file的第二行头文件时出现错误!
IUT的含义在函数头有注释说明:
thdred.f是被trot.f调用的,查看/opt/gamit10.71/gamit/orbits/trot.f
出现intin变量在openb.f中边赋值:
打开/opt/gamit10.71/gamit/orbits/openb.f后,看到了IUTIN=16的赋值!
终于排查到At line 140 of file thdred.f (unit = 16, file = 'tbrdce.161')这句话错误原因!
OPEN ( UNIT=IUTIN,FILE=tfin,FORM='UNFORMATTED',STATUS='OLD',iostat=ioerr )
注意在Fortran代码中,读取非格式文件
读取文件的时候出现错误,查找写入的情况(thdrit.f为写入头文件函数)
写入T-file时,第一行语法如下:
WRITE(iut) HEAD,IME,IDE,IYE,HE,XMINE,SECE
1 ,IM0,ID0,IY0,H0,XMIN0,SEC0
2 ,IMF,IDF,IYF,HF,XMINF,SECF
3 ,DELT,NEPOCH,UT1S,XPOLE,YPOLE
但读取文件的时候为:
read(iut) head,ite,tee,itb,tbb,itstp,tstp,sdelt,nepcht
然而,第二句头文件部分写入和读取格式一致:
write(iut) comt,nsat,nintrs
. , (satnam(isat),(satics(i,isat),i=1,nics),isat=1,nsat)
read(iut) comt,nsat,nintrs
. , (satnam(isat),(tsatic(i,isat),i=1,nics),isat=1,nsat)
本错误的原因, 很可能就是写入和读取没有严格对应,造成数据读取错误!!
还需要深入研究!对Fortran语法也是一知半解,了解的不够深入!
Fortran中open中有很多参数可以使用,详细如下:
OPEN(UNIT=number, FILE='filename', FORM='...', STATUS='...', ACCESS='...', RECL=length, ERR=label, IOSTAT=iostat, BLANK='...', POSITION='...', ACTION=action, PAD='...', DELIM='...')
UNIT= 'number': number必须是一个正整数,它可以使用变量或是常量来赋值。number最好避开1,2,5,6。因为2,6是默认的输出位置,也就是屏幕。1,5则是默认的输入位置,键盘。
FILE= 'filename': 指定要打开的文件名称,文件名要符合系统规定。windows下不区分大小写,unix下则会区分大小写,最好不要使用中文文件名。
FORM ='FORMATTED' OR 'UNFORMATTED'
FORM字段只有两个值可以设置:
FORM='FORMATTED' “文本文件”格式来保存
FORM='UNFORMATTED' “二进制文件”格式保存
这一栏不给定时候的默认值是: FORM='FORMATTED'
STATUS ='NEW' or 'OLD' or 'SCRATCH' or 'UNKNOWN' 用来说明打开一个新的文件或已经存在的旧文件。
STATUS='NEW' 打开一个原本不存在的新文件
STATUS='OLD' 打开一个原来已经存在的文件
STATUS='REPLACE' 若文件已经存在则重新创建一次,原来的内容消失;若不存在则会创建新文件。
STATUS='SCRATCH' 表示要打开一个暂存文盘,这个时候可以不需要指定文件名称,也就是FILE这个一栏可以忽略。因为程序本身会自动取一个文件名,至于文件名是啥也不重要,因为暂存盘会在程序结束后自动删除。
STATUS='UNKNOWN' 由各编译器自定义。通常会同REPLACE的效果。
!这一栏不给定时,默认为STATUS='UNKNOWN'。
ACCESS ='SEQUENTIAL' or 'DIRECT' 设置读写文件的方法:
ACCESS='SEQUENTIAL' 读写文件的操作会以“顺序”的方法来做读写,“顺序读取文件”。
ACCESS='DIRET' 读写文件的操作可以任意指定位置,“直接读取文件”。
!不赋值时候,默认为: ACCESS='SEQUENTIAL'。
RECL =length 在顺序读取文件中,RECL字段值用来设置一次可以读取多大容量的数据。
打开“直接读取文件”,RECL=length的length值是用来设置文件中每一个模块单元的分区长度。
length的单位在文本根式下为1个字符,也就是1 byte。在二进制格式下则由编译器自行决定,一般可能为1 byte (G77) 或 4 byte (Visual Fortran)。
ERR=LABEL 这个字段用来设置当文件打开发生错误时,程序会跳跃到LABEL所指定的行代码处来继续执行程序。
IOSTAT=var 这个字段会设置一个整数值给后面的整型变量,这是用来说明文件打开的状态,数值会有下面三种情况:
var>0 表示读取操作错误
var=0 表示读取操作正常
var<0 表示文件终了
BLANK ='NULL' or 'ZERO' 用来设置输入数字时,当所设置的格式字段中有空格存在时所代表的意义。
BLANK='NULL'时,空格代表没有东西。BLANK='ZERO'时,空格部分会自动以0代入。
以下是Fortran 90添加的功能:
POSITION ='ASIS' or 'REWIND' or 'APPEND' 设置文件打开时候的读写位置:
POSITION='ASIS' 表示文件打开时的读取的位置不特别指定,通常就是在文件的开头。是默认值。
POSITION='REWIND' 表示文件打开时的读取位置移到文件的开头。
POSITION='APPEND' 表示文件打开时的读取位置移到文件的结尾。
ACTION ='READ' or 'WRITE' or 'READWRITE' 设置打开文件的读写权限:
ACTION='READWRITE' 表示所打开的文件可以用来读取及写入,这是默认值。
ACTION='READ' 表示所打开的文件只能用来读取数据。
ACTION='WRITE' 表示所打开的文件只能用来写入数据。
PAD ='YES' or 'NO'
PAD='YES' 在格式化输入时,最前面的不足字段会自动以空格填满,默认值是
http://fcode.cn/guide-86-1.html
Fortran流文件-读写二进制任意位置
一. Fortran 读取二进制文件的直接读取法
本站曾发布文章:《Fortran 二进制文件读写》,介绍了以直接读取法进行二进制文件读写的方法。阅读本文前,如有必要,您可先阅读此文,以便了解二进制文件的基本概念。
直接读取(Access = 'Direct' )时,需指定记录长度(RecL)。
而不少二进制文件,其结构不规则,间或有 2 字节、4 字节 或 8 字节、甚至其他长度的数据,例如 SEGY 记录、Surfer 的 grid 网格化文件,此时使用直接读取会显得非常笨拙,常常需要多次 Open 同一个文件,使用不同的 RecL,以便读写特定的数据。
网络上曾有不少文章,介绍可以自由读写任意字节或位置的 fortran 代码,但通常使用扩展的语法实现。或者通过调用操作系统的 API 实现,不规范、只适合一部分编译器。
二. 流文件的基本用法
流文件(access="stream")是 Fortran2003 新增的一种读写方式,目前主流的尚在更新的编译器均支持。(包括但不限于 IVF、GFortran、PGI、NAG、Lahey、Ftn95、Absoft ,不含 CVF 和 PowerStation )
它是一种读写方式,而不是文件本身的格式。它并不把二进制文件视为一个一个的“记录”,而是视为一个整体。因此,无需指定记录长度(RecL)。
文件打开后,操作位置就在文件的第一个字节上,每次读取多少字节,就自动向后移动多少字节。下一次读写紧接着此处。
同时,流文件也提供任意位置(字节数),以及查询当前位置的方法。
1. 打开流文件
一个典型的流文件读写二进制,可使用以下语句:
Open( 12 , File = "fcode_test.bin" , access="stream" , form = "unformatted" )
access 指定打开方式为流文件,form 指定文件为无格式文件(二进制文件)
2.读写
读写时也无需指定记录(rec),典型的读取语句:
Read( 12 ) 变量1 , 变量2 , 变量3...... 变量 N
此时,在当前操作位置读写。读写后,操作位置自动向后移动 M 个字节(M等于所有读写的变量占有的字节数)
注意:无格式读写,不能指定格式,也不能写 *
如果想在其他位置读写,可使用这样的语句:
Read( 12 , pos = i ) 变量1 , 变量2 , 变量3...... 变量 N
此时,在第 i 个字节处开始读取。读写后,操作位置相对 i 向后移动 M 个字节(M 同上)
3.查询当前操作位置
经过若干 read 语句或 write 语句后,可能就不知道当前读取位置在哪儿了。此时,可通过 Inquire 查询:
Inquire( 12 , Pos = i )
以上语句执行后,i 的值会变为 12 号文件当前的操作位置(字节数)
4.设置当前操作位置
我们经常要跳过若干字节,或回退若干字节进行读写。这可以通过查询操作位置后,加减一定数量,再设置为当前操作位置。例如:
Inquire( 12 , Pos = i )
Read( 12 , Pos= i + 32 , iostat = iErr )
用 Read 语句来设置当前位置为 i + 32(即向后跳过 32 字节),而 Read 后面没有任何变量。
iostat = iErr 可以防止超过文件大小而出错。
5.关闭流文件
使用 Close(12) 关闭,与常规文件没有区别。
可以看出,流文件方式读写,比直接读写更简单,更容易理解。
三. 读取 Surfer 网格化 grd 文件的范例
Surfer 是 Goldensoft 公司出品的一款绘图软件,以等值线绘制为特长,广泛应用在地质、水文等领域。其 grd 文件为(二维)网格化文件。
这种文件有两个版本。6.0 的单精度版本、7.0以上的双精度版本。在这里,我们读取 6.0 的单精度版本,因为它比 7.0 更不规则,更能体现流文件的强大与方便。
以下是它的格式说明
可以看出,里面有 4 字节的 char(标识),2 字节的 short(网格大小),8 字节的 double(网格边界:XYZ的最小值最大值),以及 4 字节的 float(网格矩阵)
如果使用直接读写,需要分别考虑读写不同长度数据的记录长度 RecL,多次打开文件。而使用流文件方式,就非常的方便了。
01 | Program www_fcode_cn |
02 | Use , Intrinsic :: ISO_C_BINDING !// 使用内部模块,保持与 C 语言变量类型一致 |
03 | Implicit None |
04 | character ( len = 4 ) :: flag !// 4字节的标识,必须为 “DSBB” |
05 | Integer ( kind = C_SHORT ) :: m , n !// 网格大小 |
06 | Real ( Kind = C_DOUBLE ) :: rXMin , rXMax !// X Y Z 的边界 |
07 | Real ( Kind = C_DOUBLE ) :: rYMin , rYMax |
08 | Real ( Kind = C_DOUBLE ) :: rZMin , rZMax |
09 | Real , allocatable :: d ( : , : ) !// 网格矩阵 |
10 | integer :: i |
11 | Open ( 12 , File = "fcode_test.grd" , access = "stream" , form = "unformatted" ) |
12 | Read ( 12 ) flag |
13 | Write ( * , * ) 'flag=' , flag |
14 | Read ( 12 ) m , n |
15 | Write ( * , * ) 'M/N=' , m , n |
16 | allocate ( d ( m , n ) ) |
17 | Read ( 12 ) rXMin , rXMax , rYMin , rYMax , rZMin , rZMax |
18 | write ( * , * ) 'X_Min=' , rXMin , 'X_Max=' , rXMax |
19 | write ( * , * ) 'Y_Min=' , rYMin , 'Y_Max=' , rYMax |
20 | write ( * , * ) 'Z_Min=' , rZMin , 'Z_Max=' , rZMax |
21 | Inquire ( 12 , Pos = i ) !// 查询当前位置 |
22 | write ( * , '(a,1x,i4,1x,a)' ) '头部信息一共' , i -1 , '字节' !//当前操作位置 i 字节 |
23 | Read ( 12 ) d ( : , : ) |
24 | Do i = 1 , n |
25 | write ( * , '(999f6.3)' ) d ( : , i ) |
26 | End Do |
27 | Close ( 12 ) |
28 | End Program www_fcode_cn |
以上代码有注释,相信很容易理解。您可以点这里下载示范数据:focde_test.grd
如果您对派生类型(type)有一定了解,您还可以更方便的一次读取整个头部信息。
01 | Program www_fcode_cn |
02 | Use , Intrinsic :: ISO_C_BINDING !// 使用内部模块,保持与 C 语言变量类型一致 |
03 | Implicit None |
04 | Type , Bind ( C ) :: GRAD_HEAD |
05 | character ( len = 4 ) :: flag !// 4字节的标识,必须为 “DSBB” |
06 | Integer ( kind = C_SHORT ) :: m , n !// 网格大小 |
07 | Real ( Kind = C_DOUBLE ) :: rXMin , rXMax !// X Y Z 的边界 |
08 | Real ( Kind = C_DOUBLE ) :: rYMin , rYMax |
09 | Real ( Kind = C_DOUBLE ) :: rZMin , rZMax |
10 | End Type GRAD_HEAD |
11 | Type ( GRAD_HEAD ) :: Head |
12 | Real , allocatable :: d ( : , : ) !// 网格矩阵 |
13 | integer :: i |
14 | Open ( 12 , File = "fcode_test.grd" , access = "stream" , form = "unformatted" ) |
15 | Read ( 12 ) HEAD |
16 | allocate ( d ( HEAD % m , HEAD % n ) ) |
17 | Write ( * , * ) 'flag=' , HEAD % flag |
18 | Write ( * , * ) 'M/N=' , HEAD % m , HEAD % n |
19 | write ( * , * ) 'X_Min=' , HEAD % rXMin , 'X_Max=' , HEAD % rXMax |
20 | write ( * , * ) 'Y_Min=' , HEAD % rYMin , 'Y_Max=' , HEAD % rYMax |
21 | write ( * , * ) 'Z_Min=' , HEAD % rZMin , 'Z_Max=' , HEAD % rZMax |
22 | Inquire ( 12 , Pos = i ) !// 查询当前位置 |
23 | write ( * , '(a,1x,i4,1x,a)' ) '头部信息一共' , i -1 , '字节' !//当前操作位置 i 字节 |
24 | Read ( 12 ) d ( : , : ) |
25 | Do i = 1 , HEAD % n |
26 | write ( * , '(*(f6.3))' ) d ( : , i ) |
27 | End Do |
28 | Close ( 12 ) |
29 | End Program www_fcode_cn |
输出结果应为:
尝试解决:
OPEN ( UNIT=IUTIN,FILE=tfin,ACCESS='STREAM',
. FORM='UNFORMATTED',STATUS='OLD',iostat=ioerr )
重新编译出现语法错误:
openb.f:71:69:
OPEN ( UNIT=IUTIN,FILE=tfin,ACCESS='STREAM',FORM='UNFORMATTED',STATUS='OLD'
Error: Syntax error in OPEN statement at (1)
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2025-1-1 18:42
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社