Millemila
Millemila

Reputation: 1662

How to know from within a Fortran code if a file is opened by any program (Windows 7)

I have a Fortran code that updates in real time the content of a text file by adding some new real time measuraments at the very bottom of it. This text file is used (reading only) both by a fluid dynamics code (that continuously runs in real time) and by another executable built from matlab code (that performs plotting). I want to add a line in the Fortran code that says: update the text file ONLY IF it is not opened by any other program. I tried using INQUIRE:

do
   INQUIRE(FILE = filename,OPENED = ISopen)
      if (.not.ISopen) then
         ADD NEW MEASUREMENTS HERE
         exit
      endif
   endif
enddo

and before running this fortran program I opened the file with textpad. However, the variable ISopen is false. So I guess maybe INQUIRE only works for testing if file is opened within the fortran program itself. In fact if I add at the beginning of the above snippet of code:

OPEN (33,FILE = filename)

then ISopen is true. I then created an executable from a fortran code containing only:

OPEN (33,FILE = filename)
pause
CLOSE(33)

and I run it and let it in a paused status. I then run the first code I posted above and ISopen is still false. Any idea how to test if a file is open by any other program from within Fortran? My operative system is windows 7. thanks

Upvotes: 3

Views: 1173

Answers (2)

Millemila
Millemila

Reputation: 1662

At the end I solved in this way. I could not find a way to know if the file is opened, and even if there was a way it could still happen that some other program opens it right between the time I check if its open and then I modify it. Therefore, I just create a temporary copy of the file to modify, I modify this temporary copy and then I move the file back by overwriting the original one. The latter operation is performed only if the file is not locked (i.e. no other program opened the file to read the data), so I keep trying to copy it until it succeeds. I tested in many situations and it works. The code is:

   USE IFPORT
   IMPLICIT NONE
   character*256 :: DOScall
   logical :: keepTRYING
   integer :: resul

    DOScall = 'copy D:\myfile.txt D:\myfile_TMP.txt'  !create temporary copy 
    resul = SYSTEM(DOScall)        
    open(15,file ='D:\myfile_TMP.txt',form = 'formatted')
    !.... perform here some writing operations on myfile_TMP........
    close(15)
    do 
       resul = SYSTEM('move D:\myfile_TMP.txt D:\myfile.txt')
       if (resul==0) then
          exit
       else 
          pause(10)
       endif
    enddo  

Note that works perfectly fine for multiple programs performing reading and one program writing in the file (as in my case where I have 2 programs reading and only one writing). If multiple programs write the same file I guess some other parallel techniques have to be used.

Upvotes: 2

innoSPG
innoSPG

Reputation: 4656

I do not think it is possible to check if a file is opened by an external process. Some programming languages allow you to check if the file is locked or not, and that is still far from telling you if the file is opened or not, both program must acquire and release system lock for it to really work. To my knowledge, the standard fortran does not have that feature directly, but you can use the semaphore from C with the interoperability stuff.

Most user application (editors mostly) however, before updating a file, usually check if the content on the disk has changed since they capture a copy, and alert the user. They also do that if they lost and acquire the focus. If you restrict your goal to updating only if the content has not changed since you opened it, you can do the same or simply open-add and close any time you want to add a new entry. A good editor will notify the user on the other side that the content had been change by another process.


An alternative is to simulate a lock yourself and buffer the data in fortran. By buffering I mean, collect some new data (let say 100, 1000 or whatever number that is convenient) and send them to the file at once. For each update, you open, update and close the file. Your lock can be made of two simple files (emptys one for example), one created by the reader (matlab) and the other created by writer (fortran program). Let name them reading.ongoing for the reader and writing.ongoing for the writer. On the fortran side, you do the following anytime you have collected enough data to write:

  1. check for the existence of reading.ongoing (using inquire function), proceed only if it does not exist
  2. create writing.ongoing
  3. check for the existence of reading.ongoing again, if it exists, delete writing.ongoing and go back to step 1. If it does not exist, proceed forward.
  4. open, write the data and close the data file
  5. delete writing.ongoing

On matlab side, do similar thing, inverting the role of reading.ongoing and writing.ongoing.

In an exceptional race condition you could be blocked because they are all trying at the same time. In that case, you could modify the step 1. of matlab to force it to wait for few millisecond before proceeding. This will get you on the road as long as none of the program get killed between step 1 and 5.


You can also use semaphore with the interoperability stuff in fortran. See the following post for example. You can also similar think on the side of matlab, I do not have any example. That will lower your headhache and let the system manage the lock for you.

Upvotes: 1

Related Questions