参考资料:彭国论,《Fortran 95程序设计》,2002年
第9章
- 顺序访问文件
- 直接访问文件
- 二进制文件的操作
- 内部文件
1. 顺序访问文件
顺序文件读写时,不能任意赋值到文件的某个位置读写数据,只能从头开始一步步向下进行。改变文件读写位置时,只能一步步地进退,或是直接移回文件开头。
EX0906.F90的实现
! 自定义的student数据结构
module typedef
!?implicit none
type student
integer CH, MA, EN ! 成绩
end type student
end module typedef
program Chapter9
use typedef ! student数据结构在该module中被定义
implicit none
! Page 244, EX0906
! write information of student into file
call write2txt()
end program Chapter9
subroutine write2txt ()
use typedef
implicit none
! INPUT VARIABLES
! LOCAL VARIABLES
type(student), allocatable :: stu(:) ! 数据结构的数组
integer :: stu_num ! 学生的个数,即数组大小
integer :: alloc_err ! 可变数组是否申请内存成功
integer :: counter ! 计数器
integer :: unitid = 10
integer :: varstat
character(len=80) :: filename='data.txt' !文件名称
! step1: define the number
write(*,*) 'Please define the number of students:'
read(*,*) stu_num
! step2: allocate the arrary
allocate(stu(stu_num), stat = alloc_err)
if( alloc_err /=0 ) then
stop
end if
! step3: read the information from keyboard (you should type them)
do counter=1, stu_num
write(*,*) 'No. ', counter
read(*,*) stu(counter)%CH, stu(counter)%MA, stu(counter)%EN
end do
! step4: write it into the file
open( unit=unitid, file=filename, access="sequential", iostat=varstat)
if(varstat/=0) then
stop
end if
do counter=1, stu_num
write( unit = unitid, fmt = "( 'No.', I2, /, 'Chinese:', I2, 'Math:', I2, 'English:', I2 )")&
counter, stu(counter)%CH, stu(counter)%MA, stu(counter)%EN
end do
close( unit=unitid )
end subroutine write2txt
2. 直接访问文件
把文件的空间、内容事先分区成好几个同样大小的小模块,这些模块会自动按顺序编号。读写文件时,要先赋值文件读写位置在第几个模块,再来进行读写的工作。
书中所给的例子实用性不大,将进行直接访问文件时的要点摘录如下:
- OPEN命令中设置ACCESS='DIRECT'时,同时需设定RECL字段,即所谓模块的大小。
- ACCESS='DIRECT'时,FORM的默认值是'UNFORMATTED'(即二进制)
- Windoes系统中,文本文件的每一行的行尾都有两个看不见的符号用来代表一行文本的结束。所以一行文本的长度是“这一行文本的字符数量再加上2”。UNIX系统中,行尾又一个看不见的符号来表示文件的结束。
在Notepad++中进行point 3的验证,注意底部状态栏:
Windows(CR LF) length=6, Pos=7
Unix(LF) length=5, Pos=6
3. 二进制文件
OPEN命令中的RECL字段所设置的整数n值所代表的大小会随着编译器不同而改变。有的编译器会视为n bytes(比如G77),有的编译器会视为n*4 bytes(比如Visual Fortran)。 ==> 通过编译设置(RECL)来提高不同编译器间的运行结果是相同的?!
此处给出类似于EX0912.F90的代码
subroutine write2bin()
implicit none
real :: salary(9) = (/1.2, 1.3, 1.2, 1.5, 0.8, 2.0, 2.5, 5.6, 1.8/)
integer :: varstat, unitid=10, index
character(len=80) :: filename="list.bin"
open( unit=unitid, file=filename, form='unformatted', &
access='direct', recl=1, status='replace' )
do index=1,9
write( unitid, rec=index ) salary(index)
end do
close( unitid )
end subroutine write2bin
文件大小为36 bytes,使用的ivf(intel visual fortan)编译器
???修改编译器中real类型的默认大小,对文件大小并不起作用(仍旧为36字节),因为小数点后仅跟随一个数字?回顾浮点类型的精度
4. 内部文件
可理解为暂存在内存中的文件,应用场景之一为读取用户输入时,提高容错性。比如,让用户输入整型,但用户输入的是'123acd', '#23&'这类非法输入,可使用内部文件机制对输入进行检查。实现起来,即将用户输入读取为字符串,若符合要求,可将其读取为整型。
integer :: getinteger
character(len=80) :: string
! read from default input (keyboard)
read(*,*) string
! check whether string can be converted into integer
read(string, *) getinteger ! notice, unit=string