如何检查文件是否已在tcl中打开

时间:2013-10-25 15:09:15

标签: file-io tcl

我有一个tcl程序,我打开一个文件,如果不存在则创建写入。现在我在其中记录一些puts语句以进行调试。现在在这个过程结束时,我关闭文件。但在中间我调用另一个proc,我需要在该proc中的这个打开的文件中写一些东西。所以我想做这样的事情:

proc ::myproc {args} { 
  set fp [open "C:\\log.txt" w+];
  puts $fp "Checkpoint 1";
  set retVal [::myprocII];
  puts $fp "Checkpoint 2";
  close $fp;
  return 1;
}

proc ::myprocII {} {
  set fp [open "C:\\log.txt" w+];
  puts $fp "Checkpoint 3";
  close $fp;
  return 1;
}

因为我在myprocII中打开相同的文件并记录数据并关闭它,所以它不是错误或异常的原因。然后我仍然在我的调用proc myproc中记录数据,即使我关闭了myprocII中的文件。我尝试测试这个但是因为我从批处理文件运行它,窗口关闭然后我才能弄清楚错误是什么。

所以我想知道这是否正确,或者如果不是,我如何继续将数据附加到不同程序的同一日志文件中。

1 个答案:

答案 0 :(得分:4)

有几个选择:

  • 使用1个文件描述符,在程序结束时关闭它。

    proc log {data} {
        global logfd
        if {![info exists logfd] || $logfd == ""} {
            set logfd [open {C:\log.txt} w]
        }
        puts $logfd $data
    }
    
    # before you exit, close it:
    catch {close $::logfd}
    

    当程序终止时,Tcl应该在退出时关闭文件。

  • 打开/关闭每次写入的文件。仅在附加模式中有用

    proc log {data} {
        set fd [open {C:\log.txt} a]
        catch {
            puts $fd $data
        } res opt
        close $fd
        return -options $opt $res
    }
    

    这不是最高效的解决方案,但它很干净。

  • 使用一些黑客

    rename open _open
    rename close _close
    proc open {path args} {
       global sharedfd
       if {$path eq {C:\log.txt}} {
           if {[info exists sharedfd] && [dict exists $sharedfd fd]} {
               dict incr sharedfd refcount
               return [dict get $sharedfd fd]
           } else {
               set fd [_open $path {*}$args]
               dict set sharedfd fd $fd
               dict set sharedfd refcount 1
               return $fd
           }
       }
       return [_open $path {*}$args]
    }
    
    proc close {fd args} {
        global sharedfd
        if {[info exists sharedfd] 
                && [dict exists $sharedfd fd] 
                && [dict get $sharedfd fd] eq $fd} {
            dict incr sharedfd refcount -1
            if {[dict get $sharedfd refcount] <= 0} {
               _close $fd
               unset sharedfd
            }
            return
        }
        _close $fd {*}$args
    }
    

    如果C:\log.txt已经打开,则返回相同的fd,保留refcounter,当refcount为0时关闭通道。 请注意,这是一个黑客攻击。您可能不应该修改标准命令。