2

我需要将一些日志存储在一个文件中,该文件可以随着每次执行而增长。一个合乎逻辑的方法是a+在打开时使用选项,因为使用w+会截断文件。但是,使用a+选项(Tcl 8.4)我无法在文件中的任何地方写入。seek工作正常。我可以验证指针是否已使用tell. 但是输出总是在文件的末尾完成。

有没有办法解决这个问题?即有能力在任何地方寻找和写入,并在打开时保留旧文件。

4

3 回答 3

4

在 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需要并且非常难以正确模拟任何其他方式)。

于 2012-11-06T09:14:40.287 回答
3

打开方式r+- 它以读取模式打开(因此不会转换文件),但也允许写入。

open有关更多信息,请参阅文档: http ://www.tcl.tk/man/tcl8.5/TclCmd/open.htm

于 2012-11-06T03:37:19.990 回答
0

我已经验证使用该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命令的包。

于 2012-11-06T07:02:45.290 回答