【问题标题】:How to know from within a Fortran code if a file is opened by any program (Windows 7)如何从 Fortran 代码中知道文件是否被任何程序打开(Win​​dows 7)
【发布时间】:2016-04-16 05:13:49
【问题描述】:

我有一个 Fortran 代码,它通过在文本文件的最底部添加一些新的实时测量值来实时更新文本文件的内容。该文本文件由流体动力学代码(实时连续运行)和另一个从 matlab 代码构建的可执行文件(执行绘图)使用(只读)。我想在 Fortran 代码中添加一行:仅当文本文件未被任何其他程序打开时才更新文本文件。我尝试使用 INQUIRE:

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

在运行这个 fortran 程序之前,我用 textpad 打开了文件。但是,变量 ISopen 为假。所以我想也许 INQUIRE 仅适用于测试文件是否在 fortran 程序本身中打开。其实如果我在上面sn-p的代码开头加上:

OPEN (33,FILE = filename)

那么 ISopen 为真。然后,我从仅包含以下内容的 fortran 代码创建了一个可执行文件:

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

然后我运行它并让它处于暂停状态。然后我运行我在上面发布的第一个代码,ISopen 仍然是错误的。知道如何测试文件是否被 Fortran 中的任何其他程序打开?我的操作系统是windows 7。 谢谢

【问题讨论】:

  • 我知道 vim 在用户编辑文件时创建了一个交换文件。也许 textpad 有类似的东西?
  • 我也这么认为。但是然后“我然后从 fortran 代码创建了一个可执行文件”,但它仍然没有显示为打开

标签: file fortran locking


【解决方案1】:

最后我以这种方式解决了。我找不到知道文件是否打开的方法,即使有一种方法,在我检查它是否打开然后我修改它的时间之间,其他程序仍然会打开它。因此,我只是创建了要修改的文件的临时副本,我修改了这个临时副本,然后通过覆盖原始文件将文件移回。仅当文件未锁定(即没有其他程序打开文件来读取数据)时才执行后一个操作,因此我一直尝试复制它直到它成功。我在许多情况下进行了测试,并且可以正常工作。代码是:

   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  

请注意,对于在文件中执行读取和写入一个程序的多个程序(如我有 2 个程序读取和只有一个写入的情况),它工作得非常好。如果多个程序编写同一个文件,我想必须使用其他一些并行技术。

【讨论】:

    【解决方案2】:

    我认为无法检查文件是否被外部进程打开。一些编程语言允许您检查文件是否被锁定,但这仍然不能告诉您文件是否打开,两个程序都必须获取和释放系统锁才能真正工作。据我所知,标准 fortran 不直接具有该功能,但您可以将 C 中的信号量与互操作性内容一起使用。

    然而,大多数用户应用程序(主要是编辑器)在更新文件之前,通常会检查磁盘上的内容是否在捕获副本后发生了变化,并提醒用户。如果他们失去并获得焦点,他们也会这样做。如果您将目标限制为仅在内容自打开后未更改的情况下进行更新,您可以执行相同操作,或者在您想要添加新条目时随时打开-添加并关闭。一个好的编辑器会通知另一端的用户内容已被另一个进程更改。


    另一种方法是自己模拟锁并在fortran中缓冲数据。通过缓冲我的意思是,收集一些新数据(比如说 100、1000 或任何方便的数字)并立即将它们发送到文件中。对于每次更新,您打开、更新和关闭文件。 您的锁可以由两个简单的文件(例如一个空文件)组成,一个由阅读器(matlab)创建,另一个由编写器(fortran 程序)创建。让他们为读者命名为reading.ongoing,为作者命名为writing.ongoing。 在 fortran 方面,只要您收集到足够的数据进行写入,您就可以执行以下操作:

    1. 检查 reading.ongoing 是否存在(使用查询功能),仅在不存在时继续
    2. 创建写作.ongoing
    3. 再次检查reading.ongoing是否存在,如果存在则删除writing.ongoing并返回步骤1。如果不存在则继续。
    4. 打开、写入数据和关闭数据文件
    5. 删除 writing.ongoing

    在matlab方面,做类似的事情,颠倒read.ongoing和writing.ongoing的角色。

    在特殊的比赛条件下,您可能会被阻止,因为他们都在同时尝试。在这种情况下,您可以修改 matlab 的步骤 1. 以强制它在继续之前等待几毫秒。只要在第 1 步和第 5 步之间没有程序被终止,这将使您上路。


    您还可以将信号量与 fortran 中的互操作性内容一起使用。例如,请参阅following post。你也可以在matlab方面进行类似的思考,我没有任何例子。这将减轻您的头痛并让系统为您管理锁定。

    【讨论】:

    • 谢谢。我主要担心的是我的代码读取了我保存它的文本文件,它读取的可能只是导致它崩溃的部分修改..
    • 我明白了,这是一个凝灰岩的情况。我更新了一个建议。
    • 老实说,我尝试使用此解决方案,但我无法使其工作,我也不确定这是否安全。我发布了一个经过我测试和工作的更简单的答案。
    • @Alberto,目标不是接受没有帮助的答案。解决问题并发布解决方案很好。我只是想为每个已解决的问题提供一个公认的解决方案是件好事。
    猜你喜欢
    • 2013-07-16
    • 1970-01-01
    • 1970-01-01
    • 2016-03-21
    • 1970-01-01
    • 2012-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多