Tcl 程式設計/檔案操作
除了 C 語言中的 stdio 庫中已知的功能外,Tcl 還提供了一些用於處理檔案的命令,類似於 Shell 提供的功能,儘管通常更冗長。以下是一些示例
glob *.tcl
列出當前目錄中與模式 *.tcl 匹配的所有檔案。
file copy /from/path/file.ext /to/path . file delete /from/path/file.ext . file rename before.txt after.txt . cd /an/other/directory . pwd
要讓程式碼在另一個目錄中臨時執行,可以使用此模式
set here [pwd] cd $someotherdir #... code here cd $here
更準確地說,許多“檔案”操作通常在“通道”上工作,它們可以是
- 標準通道 (stdin、stdout、stderr)
- 使用 open ... 開啟的檔案
- 使用 'open |... 開啟的管道
- 套接字 (TCP)
檔案通常使用路徑名來訪問,它指示它們在目錄樹中的位置。與 Unix 一樣,Tcl 使用 "/" 作為路徑分隔符,而在 Windows 上 "\" 是本機方式 - 這不僅會給 Tcl 帶來麻煩,甚至會給 C 帶來麻煩,因為 "\" 在兩者中都是跳脫字元,因此例如 \t 被解析為水平製表符,\n 被解析為換行符等。幸運的是,Windows 本機也接受 "/",因此您可以在 Tcl 和 C 程式中使用正斜槓作為路徑分隔符,而無需擔心。但是,您仍然需要注意轉義序列。一個權宜之計是
- 轉義跳脫字元,即為 \, 寫 \\,或
- 將反斜槓名稱括起來,例如 {\foo\bar\grill.txt}
但 Tcl 允許在幾乎所有情況下使用“正常”分隔符 /,所以使用它更安全。不幸的是,對於 Mac 使用者來說,情況很糟糕,因為 MacOS(在 X 之前)只接受 ":" 作為檔案分隔符。
如果您需要,以下是如何在兩種形式之間轉換
% file normalize \\foo\\bar\\grill.txt C:/foo/bar/grill.txt % file nativename /foo/bar/grill.txt \foo\bar\grill.txt
您甚至可以使用 file join 命令:file join arg1 arg2 ... argN
然後 Tcl 會處理所有平臺相關細節以建立平臺無關路徑。例如
set somepath [file join foo bar grill.txt]
將在以下路徑 (在 Windows 機器上) 上產生結果:foo/bar/grill.txt
Tcl 的輸入/輸出命令與 C 語言的 stdio 中的命令非常接近(只需去掉開頭的 f)
- set handle [open filename ?mode?]
- set data [read $handle ?int?]
- tell $handle
- seek $handle offset ?from?
- puts ?-nonewline? ?$handle? content
- gets $handle ?varname?
- close $handle
C 語言的 printf 功能分為兩步
- 使用 format 將資料格式化為字串(非常類似於 sprintf)
- 使用 puts 輸出生成的字串。例如,
puts $handle [format "%05d %s" $number $text]
要逐行處理文字檔案,您有兩種選擇。如果檔案小於幾兆位元組,您可以一次性將其讀入
set f [open $filename]
foreach line [split [read $f] \n] {
# work with $line here ...
}
close $f
對於任何大小的檔案,您可以逐行讀取(儘管這比上面的方法稍微慢一些)
set f [open $filename]
while {[gets $f line] >= 0} {
# work with $line here ...
}
close $f
最後,如果您能將檔案格式化為可執行的 Tcl 程式碼,以下讀取方法最快
source $filename
要“觸控一個檔案”,即如果不存在則建立它,並且在任何情況下更新它的修改時間,您可以使用此方法
proc touch name {close [open $name a]}
所有檔案都由位元組組成,位元組由位組成,位是二進位制的。術語“二進位制”與檔案的關係主要在於它們可以包含任何值的位元組,並且行結束符 (DOS/Windows 世界中的回車符 + 換行符) 不會被轉換。Tcl 可以毫無問題地處理“二進位制”檔案 - 只需在開啟後將通道配置為二進位制
set fp [open tmp.jpg] fconfigure $fp -translation binary set content [read $fp] close $fp
現在變數 content 按位元組儲存檔案的內容。
要測試檔案是否為“二進位制”,即它是否包含 NUL 位元組
proc binary? filename {
set f [open $filename]
set data [read $f 1024]
close $f
expr {[string first \x00 $data]>=0}
}
許多有用的檔案操作都集中在 file 命令中。第一個引數告訴要執行哪個操作
- file atime name ?time?
- file attributes name
- file attributes name ?option?
- file attributes name ?option value option value...?
- file channels ?pattern? - 返回當前開啟檔案的控制代碼
- file copy ?-force? ?- -? source target
- file copy ?-force? ?- -? source ?source ...? targetDir
- file delete ?-force? ?- -? pathname ?pathname ... ?
- file dirname name - 例如 [file dirname /foo/bar/grill.txt] -> /foo/bar
- file executable name
- file exists name
- file extension name - 例如 [file extension /foo/bar/grill.txt] -> .txt
- file isdirectory name
- file isfile name
- file join name ?name ...?
- file link ?-linktype? linkName ?target?
- file lstat name varName
- file mkdir dir ?dir ...? - 建立一個或多個目錄(資料夾)
- file mtime name ?time?
- file nativename name
- file normalize name
- file owned name
- file pathtype name
- file readable name
- file readlink name
- file rename ?-force? ?- -? source target
- file rename ?-force? ?- -? source ?source ...? targetDir
- file rootname name - 例如 [file rootname /foo/bar/grill.txt] -> /foo/bar/grill
- file separator ?name?
- file size name
- file split name - 例如 [file split /foo/bar/grill.txt] -> {foo bar grill.txt}
- file stat name varName
- file system name
- file tail name - 例如 [file tail /foo/bar/grill.txt] -> grill.txt
- file type name
- file volumes - Windows:返回您的“驅動器號”,例如 {A:/ C:/}
- file writable name