Fortran Wiki
mm_ioutils

This is a small library that I use to make the input and output routines of FORTRAN a little easier to handle. So far, it’s quite unsophisticated, but I welcome improvements here.

The main features are:

  • easy and intelligent input of command line arguments,
  • simple file opening and unit tracking.

I should point out that due to the use of getarg(), the code is not strictly F95.

Usage

Compile the code and link it to your current program. You also need to make sure that the .mod file is accessible by the program. The library can be included in the main program simply by using

use mm_ioutils

Command-line arguments

In order to read command line arguments into program variables, use the read_argument() subroutine. This takes two arguments: the first is the index of the argument on the command line (counting from 1), and the second is the variable that is to be written to (this must be of type integer, real or double precision).

! example

program example

use mm_ioutils

implicit none

integer :: test_int


call read_argument(1, test_int)
write (*,*) test_int

end program example

Compiling and then running the program as example 10 should then simply print the number 10 to the console.

File handling

The function open_file(name, st) opens a file with the prefix name (note that this may include a path) and with an optional status string st. The function returns the file unit identifier.

! example

program example

use mm_ioutils

implicit none

integer :: FTEST


FTEST = open_file("my_dir/my_file.txt")
write (FTEST, *) "Hello World!"

end program example

Note that in the above example, since we did not specify st, the file was opened with status “unknown”. Secondly, the directory my_dir must exist in the path where the program is run.

The function open_fileset(name, n) behaves similarly to open_file, except it opens a set of N files with successive unit identifiers, and all with status “unknown”. The returned integer is the unit identifier of the first opened file.

Finally, one can also set the prefix used by default for all files (this is useful for specifying a common subdirectory) by using the io_set_prefix command. For example, calling

call io_set_prefix("my_dir")

will place all subsequently created files in the subdirectory “my_dir” of the directory where the program is being run.

Code


!
! mm_ioutils.f90
! A set of file handling routines
!
! Michael Murphy, Mar. 2009
!

module mm_ioutils

  implicit none

  interface read_argument
     module procedure read_argument_int
     module procedure read_argument_float
     module procedure read_argument_float_dp
  end interface

  private

  integer :: nextunit=10
  character(50) :: fileprefix=""

  public :: open_file, open_fileset, read_argument, io_set_prefix

contains

! ------------------------------------------------------------------------------
! function open_file
! opens a file with "unknown" status and returns the unit number
  function open_file(name, st) result (id)
    character(*), intent(in) :: name
    character(*), optional :: st
    integer :: id

    id = nextunit
    nextunit = nextunit + 1

    if (.not.present(st)) then
       open (unit=id, file=trim(fileprefix)//name//".txt", status="unknown")
    else
       open (unit=id, file=trim(fileprefix)//name//".txt", status=st)
    end if

  end function open_file

! ------------------------------------------------------------------------------
! function open_fileset
! opens a set of files with numerical suffices and with "unknown" status
  function open_fileset(basename, n) result (id)
    character(*), intent(in) :: basename
    integer, intent(in) :: n
    character(3) :: suffix
    integer :: id, i

    if (n.gt.999) then
       write (*,*) "mm_fileio: More than 999 files required -- aborting"
       stop
    end if

    id = nextunit
    nextunit = nextunit + n

    do i=1,n
       write (unit=suffix, fmt='(I3)') i
       open (unit=id+(i-1), file=trim(fileprefix)//trim(basename)//"_"//trim(adjustl(suffix))//".txt", status="unknown")
    end do

  end function open_fileset

! ------------------------------------------------------------------------------
! subr read_argument_int
! reads an integer from the command line and inserts it into a variable  
  subroutine read_argument_int(index, var)
    integer, intent(in) :: index
    integer, intent(inout) :: var
    character(12) :: arg

    call getarg(index, arg)
    if (arg.ne."".and.arg.ne."?") then
       read(unit=arg, fmt='(I6)') var
    end if
  end subroutine read_argument_int

! ------------------------------------------------------------------------------
! subr read_argument_float
! reads a float from the command line and inserts it into a variable
  subroutine read_argument_float(index, var)
    integer, intent(in) :: index
    real, intent(inout) :: var
    character(12) :: arg

    call getarg(index, arg)
    if (arg.ne."".and.arg.ne."?") then
       read(unit=arg, fmt='(F20.9)') var
    end if
  end subroutine read_argument_float

! ------------------------------------------------------------------------------
! subr read_argument_float_dp
! reads a real(8) from the command line and inserts it into a variable
  subroutine read_argument_float_dp(index, var)
    integer, intent(in) :: index
    real(8), intent(inout) :: var
    character(12) :: arg

    call getarg(index, arg)
    if (arg.ne."".and.arg.ne."?") then
       read(unit=arg, fmt='(F20.9)') var
    end if
  end subroutine read_argument_float_dp

! ------------------------------------------------------------------------------
! subr io_set_prefix
! set a common prefix for all filenames
  subroutine io_set_prefix(prefix)
    character(*), intent(in) :: prefix

    fileprefix = prefix
  end subroutine io_set_prefix

end module mm_ioutils