这个名为tgrep的过程,可以说明TCL文件I/O的基本特点:
proc tgrep { pattern filename} {
set f [open $filename r]
while { [gets $f line ] } {
if {[regexp $pattern $line]} {
puts stdout $line
}
}
close $f
}
以上过程非常象UNIX的grep命令, 你可以用两个参数调用它,一个是模式,另一个是文件名,tgrep将打印出文件中所有匹配该模式的行。
下面介绍上述过程中用到的几个基本的文件输入输出命令。
open name ?access?
open命令 以access方式打开文件name。返回供其他命令(gets,close等)使用的文件标识。如果name的第一个字符是“|”,管道命令被触发,而不是打开文件。
文件的打开方式和我们熟悉的C语言类似,有以下方式:
r 只读方式打开。文件必须已经存在。这是默认方式。
r+ 读写方式打开,文件必须已经存在。
w 只写方式打开文件,如果文件存在则清空文件内容,否则创建一新的空文件。
w+ 读写方式打开文件,如文件存在则清空文件内容,否则创建新的空文件。
a 只写方式打开文件,文件必须存在,并把指针指向文件尾。
a+ 只读方式打开文件,并把指针指向文件尾。如文件不存在,创建新的空文件。
open命令返回一个字符串用于表识打开的文件。当调用别的命令(如:gets,puts,close,〕对打开的文件进行操作时,就可以使用这个文件标识符。TCL有三个特定的文件标识: stdin,stdout和stderr ,分别对应标准输入、标准输出和错误通道,任何时候你都可以使用这三个文件标识。
gets fileId ?varName? 读fileId标识的文件的下一行,忽略换行符。如果命令中有varName就把该行赋给它,并返回该行的字符数(文件尾返回-1),如果没有varName参数,返回文件的下一行作为命令结果(如果到了文件尾,就返回空字符串)。
和gets类似的命令是read,不过read不是以行为单位的,它有两种形式:
read ?-nonewline? fileId 读并返回fileId标识的文件中所有剩下的字节。如果没有nonewline开关,则在换行符处停止。
read fileId numBytes 在fileId标识的文件中读并返回下一个numbytes字节。
puts ?-nonewline? ?fileId? string puts命令把string写到fileId中,如果没有nonewline开关的话,添加换行符。fileId默认是stdout。命令返回值为一空字符串。
puts命令使用C的标准I/O库的缓冲区方案,这就意味着使用puts产生的信息不会立即出现在目标文件中。如果你想使数据立即出现在文件中,那你就调用flush命令:
flush fileId 把缓冲区内容写到fileId标识的文件中,命令返回值为空字符串。
flush命令迫使缓冲区数据写到文件中。flush直到数据被写完才返回。当文件关闭时缓冲区数据会自动flush。
close ?fileId? 关闭标识为fileId的文件,命令返回值为一空字符串。
这里特别说明的一点是,TCL中对串口、管道、socket等的操作和对文件的操作类似,以上对文件的操作命令同样适用于它们。