Reading strings from unformatted files (variable record length)

假如想象 提交于 2019-12-10 18:32:15

问题


I have an unformatted Fortran file, containing strings of different lengths, and I'm having trouble reading these strings with Fortran itself.

Sample program:

program test
implicit none
character(len=200) :: line

open(32,file="testfile",form="unformatted",action="write")
write(32) "A test string"
write(32) "Another longer test string"
close(32)

open(33,file="testfile",form="unformatted",action="read")
read(33) line
write(6,*) trim(line)
read(33) line
write(6,*) trim(line)
close(33)

end program test

This fails (compiled with gfortran) with:

At line 11 of file test.f90 (unit = 33, file = 'testfile')
Fortran runtime error: I/O past end of record on unformatted file

I could get it to work by trying the read with decreasing lengths and backspacing (read_string subroutine), but this looks highly inefficient:

program test
implicit none
character(len=200) :: line

open(32,file="testfile",form="unformatted",action="write")
write(32) "A test string"
write(32) "Another longer test string"
close(32)

open(33,file="testfile",form="unformatted",action="read")
call read_string(33,line)
write(6,*) trim(line)
call read_string(33,line)
write(6,*) trim(line)
close(33)

contains

subroutine read_string(u,string)
integer, intent(in) :: u
character(len=*), intent(out) :: string
integer :: i, error

do i=len(string),0,-1
  read(u,iostat=error) string(:i)
  if (error == 0) then
    string(i+1:) = ''
    exit
  end if
  backspace(u)
end do

end subroutine read_string

end program test

Is there a better way to read variable-length strings from unformatted files?


回答1:


I slightly reworked your sample program, reading the file in binary. This works for Intel's compiler; gfortran does not know the binary format, so ymmv. See where I got my ideas at Intel's reference on record types

program test
implicit none
character(len=200) :: line
integer(4) recl_at_start, recl_at_end

open(32,file="testfile",form="unformatted",action="write")
write(32) "A test string"
write(32) "Another longer test string"
close(32)

! initialization is required to fill the line with blanks
! because trim() does not work on line filled with zero characters
line = ""

open(33,file="testfile",form="binary",action="read")

read(33) recl_at_start
read(33) line(1:recl_at_start)
read(33) recl_at_end
write(6,*) trim(line)

read(33) recl_at_start
read(33) line(1:recl_at_start)
read(33) recl_at_end
write(6,*) trim(line)

close(33)

end program test

its output is

A test string
Another longer test string

Now that you know the line length, trim() is not really necessary anymore. Just use

write(6,*) line(1:recl_at_start)

This also prevents troubles when you add "A shorter test string" to the data.



来源:https://stackoverflow.com/questions/19464417/reading-strings-from-unformatted-files-variable-record-length

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!