我有一个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中的文件。我尝试测试这个但是因为我从批处理文件运行它,窗口关闭然后我才能弄清楚错误是什么。
所以我想知道这是否正确,或者如果不是,我如何继续将数据附加到不同程序的同一日志文件中。
答案 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时关闭通道。
请注意,这是一个黑客攻击。您可能不应该修改标准命令。