我需要将一些日志存储在一个文件中,该文件可以随着每次执行而增长。一个合乎逻辑的方法是a+
在打开时使用选项,因为使用w+
会截断文件。但是,使用a+
选项(Tcl 8.4)我无法在文件中的任何地方写入。seek
工作正常。我可以验证指针是否已使用tell
. 但是输出总是在文件的末尾完成。
有没有办法解决这个问题?即有能力在任何地方寻找和写入,并在打开时保留旧文件。
我需要将一些日志存储在一个文件中,该文件可以随着每次执行而增长。一个合乎逻辑的方法是a+
在打开时使用选项,因为使用w+
会截断文件。但是,使用a+
选项(Tcl 8.4)我无法在文件中的任何地方写入。seek
工作正常。我可以验证指针是否已使用tell
. 但是输出总是在文件的末尾完成。
有没有办法解决这个问题?即有能力在任何地方寻找和写入,并在打开时保留旧文件。
在 Tcl 8.5 中,Tcl在 Unix 上的行为发生了变化,以便将O_APPEND
标志传递给open()
系统调用。这会导致操作系统始终将数据附加到文件中,并在将 FD 传递给子进程时继承;对于日志,这完全是正确的。(在 8.4 及之前的版本中,以及在 Windows 上的所有版本中,行为是在 Tcl 的文件通道实现内部模拟的,这将在内部seek()
紧接在write()
; 之前结束,当有多个进程登录到时,这显然会受到竞争条件的潜在问题同一个文件,当 FD 传递给子进程时绝对不安全。)您可以使用chan truncate
(8.5 中的新功能)管理打开文件的截断,这在a+
-打开的文件。
如果您不希望寻求结束行为,则不应使用a+
(或a
)。尝试r+
或一些标志组合,如下所示:
set f [open $filename {RDWR CREAT}]
为了比较,该a+
选项现在与 flags完全相同RDWR CREAT APPEND
,并且并非所有较长标志的组合都可以用短格式标志说明符来描述。如果您没有指定APPEND
,则需要seek $f 0 end
自己做(如果您要附加到日志,请注意多个进程的问题;这时APPEND
需要并且非常难以正确模拟任何其他方式)。
打开方式r+
- 它以读取模式打开(因此不会转换文件),但也允许写入。
open
有关更多信息,请参阅文档: http ://www.tcl.tk/man/tcl8.5/TclCmd/open.htm
我已经验证使用该a+
选项允许我在文件中的任何位置读/写。但是,通过在文件的中间(或开头)写入,我会覆盖那里的数据,而不是插入。以下代码说明了这一点:
#!/usr/bin/env tclsh
# Open the file, with truncation
set f [open foo w]
puts $f "one"
puts $f "two"
close $f
# Open again, with a+ ==> read/write/append
set f [open foo a+]
puts $f "three" ;# This goes to the end of the file
seek $f 4 ;# Seek to the beginning of the word "two"
puts $f "2.0" ;# Overwrite the word "two"
close $f
# Open and verify the contents
set f [open foo r]
puts [read $f]
close $f
输出:
one
2.0
three
如果您要在文件中间插入,您可能需要查看fileutil
包含该::fileutil::insertIntoFile
命令的包。