Re: opening files and code cleanup



Bart Vandewoestyne <MyFirstName.MyLastName@xxxxxxxxxx> wrote:

In an attempt to make my code more readable, I have noticed that
I have a lot of the following constructs in my code:

[ .. snip file open statements .. ]

I was thinking of something like the following (untested):

subroutine checked_open(file_unit, file_name, file_action)
integer(kind=i4b), intent(in) :: file_unit
character(len=*), intent(in) :: file_name
character(len=*), intent(in) :: file_action

open(unit=file_unit, file=file_name, iostat=ios, status="replace", &
access="sequential", action=file_action, position="rewind")
if (ios /= 0) then
write(unit=*, fmt="(A)") "ERROR: could not open file "//file_name//"!"
stop
end if

end subroutine checked_open

Sorry, I only just noticed this thread. For what it's worth this is my
routine for opening files for simple sequential access:

integer function file_open(filename, opened_ok, status, append)

! A generic interface for opening files. Why? Well we don't have
! to worry about units (it is returned to us) and we can examine
! the return status to see if the file open worked -- saves
! checking for existence etc

character(len=*), intent(in) :: filename
logical, optional, intent(out) :: opened_ok
character(len=*), optional, intent(in) :: status
logical, optional, intent(in) :: append

! Local variables
character(len=7) :: mystatus
logical :: filename_exists, myappend

! Define a default return value for the function should an error
! occur
file_open = -1

! Define a default status and change it if it has been specified
! in the subroutine parameters (make it lower case also)
mystatus = 'unknown'
if (present(status)) mystatus = .lcase. status

! Check if we're appending to the file
myappend = .FALSE.
if (present(append)) myappend = append

! We initialise this to false (if it is present as a parameter)
! as we will make our tests at the start of the subroutine and
! return if we encounter a problem
if (present(opened_ok)) opened_ok = .false.

! We require a filename (ifc would prompt for one in this instance
! if we didn't trap it out here)
if (trim(filename) == '') then
if (.NOT. present(opened_ok)) then
write(stderr,*) 'FILE_FUNCTIONS :: No filename specified!'
else
return
end if
end if

filename_exists = file_exists(filename)

! We will require that an old file exists, a new file dosen't exist
if ( (mystatus.eq.'old' .and. .not. filename_exists) .or. &
(mystatus.eq.'new' .and. filename_exists) ) then
if (present(opened_ok)) then
return
else
if (filename_exists) then
write(stderr,*) 'FILE_FUNCTIONS :: ',trim(filename),' already exist
s!'
else
write(stderr,*) 'FILE_FUNCTIONS :: Cannot open "',trim(filename),'"
.. It does not exist!'
end if
STOP
end if
end if

! Grab a free unit number
file_open = freeunit()

! Attempt to open the file -- if we get an error we exit without
! setting the value of opened_ok to .TRUE.
if (myappend) then
open(unit=file_open, file=filename, status=mystatus, err=1, position='app
end')
else
open(unit=file_open, file=filename, status=mystatus, err=1)
end if

if (present(opened_ok)) opened_ok = .TRUE.

1 return

end function file_open

logical function file_exists(filename)

character(len=*), intent(in) :: filename

! We make the decision that an empty filename cannot exist as
! the inquire function barfs badly on it
if (trim(filename) == '') then
file_exists = .FALSE.
return
end if

inquire(file=filename, exist=file_exists)

end function file_exists

A couple of things to note:

1. This has evolved, so originally I just returned -1 if the open was
unsuccessful but subsequently I have added an "opened_ok" logical.
2. It is a function. I like functions. I feel it is explicit what it
is returning, without having to examine the interface to the code.
3. file_open calls file_exists and freeunit, and they are all in a
module together (I call it file_functions).
3. I don't claim this is perfect, but it might give you some ideas. I
know I have added to it over time, so I didn't think of everything
the first time I implemented it. I recently added the append thing
as I wanted to implement a 'log' routine that would shove stuff on
to the end of a logfile and I couldn't do it with this routine. In
fact, I just thought that it might be desirable to create a scratch
file in temporary filespace if no filename is specified ... hmmmmm ....

Cheerio

Aidan

--
Remove famous (dead) Italian author plus full-stop to send me email (don't
blame me about the spelling of Alighieri -- it is the sysadmin's fault!)
.



Relevant Pages

  • Re: Rename file during copy
    ... running into is deciding the filename when renaming. ... extension then append "_copy" ... The current copying method is far from finished, but the renaming ...
    (comp.lang.php)
  • Re: Multiple outputs to a CSV file
    ... You will have to make sure the filename used is identical for all related ... > orchestration and then store some of the data in CSV format. ... > can I append the results of each inbound XML document to the SAME CSV file ...
    (microsoft.public.biztalk.general)
  • Re: file numbering
    ... OEX will prepend or append a timestamp to the ... filename as well to allow for sorting based on subject / date or date / ...
    (microsoft.public.windows.inetexplorer.ie6_outlookexpress)
  • Re: string manipulation (bis)
    ... it append a f after the last digit. ... set fileId [open $fileName w] ... in your input string (as split will give you blank items in the middle of ...
    (comp.lang.tcl)