跳轉到內容

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 命令中。第一個引數告訴要執行哪個操作

  • 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
華夏公益教科書