Wauzl
Wauzl

Reputation: 971

How to read text files with possibly very long lines in Fortran

Suppose I have a text file with potentially very long lines of text, for example

short
short
reeeeeeeeeeeeeeeeeeeeeeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooonnnnggg
short as well
short

I can write a simple program which reads this file:

program main
implicit none
integer, parameter        :: BIG_NUMBER = 400
integer                   :: lun
character(len=BIG_NUMBER) :: line
integer                   :: istat

open(newunit = lun, file = 'myfile')

do
   read (lun, '(A)', iostat = istat) line
   if (istat /= 0) exit
end do

end program main

This only supports text files, where all lines are not longer than 400 characters. In C, pointers are used and a similar program would automatically support any text file.

How can I rewrite the sample program in such a way that it can read lines of all lengths?

Upvotes: 3

Views: 2584

Answers (2)

IanH
IanH

Reputation: 21431

You can use non-advancing input to read successive chunks of the line into a buffer, and then combine each chunk together to form the complete line in a deferred length character variable. For example:

subroutine get_line(lun, line, iostat, iomsg)
  integer, intent(in)           :: lun
  character(len=:), intent(out), allocatable :: line
  integer, intent(out)          :: iostat
  character(*), intent(inout)   :: iomsg

  integer, parameter            :: buffer_len = 80
  character(len=buffer_len)     :: buffer
  integer                       :: size_read

  line = ''
  do
    read ( lun, '(A)',  &
        iostat = iostat,  &
        iomsg = iomsg,  &
        advance = 'no',  &
        size = size_read ) buffer
    if (is_iostat_eor(iostat)) then
      line = line // buffer(:size_read)
      iostat = 0
      exit
    else if (iostat == 0) then
      line = line // buffer
    else
      exit
    end if
  end do
end subroutine get_line

Upvotes: 7

innoSPG
innoSPG

Reputation: 4656

Never seek another solution when you have one at hand, unless it has some limitations. Since you can do it in C and with all the interoperability stuff between C and Fortran, I suggest you write a small part of the program in C to handle the reading. The C part can be as simple as a set of 2 functions and few global variables:

  1. a function to query the size of the next line that actually reads the next line and returns its size to fortran, in addition to a EOF flag
  2. a function to get the next line data that returns the line data to fortran.

If you are using getline for example, the global variables will be the File object, the line buffer and the buffer size. In addition, you can add two other functions to be called by fortran to open and close the file, or you can handle all of that in the query function.

Upvotes: 1

Related Questions