ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 输入&输出 > 原文: [https://zetcode.com/lang/tcl/io/](https://zetcode.com/lang/tcl/io/) 在本章中,我们将使用 Tcl 中的输入和输出操作。 Tcl 有几个执行 io 的命令。 我们将介绍其中的一些。 Tcl 使用称为通道的对象读取和写入数据。 可以使用`open`或`socket`命令创建通道。 Tcl 脚本可使用三个标准通道,而无需显式创建它们。 操作系统会为每个新应用自动打开它们。 它们是`stdin`,`stdout`和`stderr`。 脚本使用标准输入`stdin`来读取数据。 脚本使用标准输出`stdout`写入数据。 脚本使用标准错误`stderr`来编写错误消息。 在第一个示例中,我们将使用`puts`命令。 它具有以下概要: ```tcl puts ?-nonewline? ?channelId? string ``` `channelId`是我们要在其中写入文本的通道。 `channelId`是可选的。 如果未指定,则采用默认值`stdout`。 ```tcl #!/usr/bin/tclsh puts "Message 1" puts stdout "Message 2" puts stderr "Message 3" ``` `puts`命令将文本写入通道。 ```tcl puts "Message 1" ``` 如果未指定`channelId`,则默认情况下写入`stdout`。 ```tcl puts stdout "Message 2" ``` 此行与上一行相同。 我们仅明确指定了`channelId`。 ```tcl puts stderr "Message 3" ``` 我们写入标准错误通道。 错误消息默认情况下转到终端。 ```tcl $ ./printing.tcl Message 1 Message 2 Message 3 ``` 示例输出。 ## `read`命令 `read`命令用于从通道读取数据。 可选参数指定要读取的字符数。 如果省略,该命令将从通道读取所有数据,直到最后。 ```tcl #!/usr/bin/tclsh set c [read stdin 1] while {$c != "q"} { puts -nonewline "$c" set c [read stdin 1] } ``` 该脚本从标准输入通道读取一个字符,然后将其写入标准输出,直到遇到`q`字符为止。 ```tcl set c [read stdin 1] ``` 我们从标准输入通道(`stdin`)读取一个字符。 ```tcl while {$c != "q"} { ``` 我们继续读取字符,直到按`q`为止。 ## `gets`命令 `gets`命令从通道读取下一行,返回行中直到(但不包括)行尾字符的所有内容。 ```tcl #!/usr/bin/tclsh puts -nonewline "Enter your name: " flush stdout set name [gets stdin] puts "Hello $name" ``` 该脚本要求用户输入,然后打印一条消息。 ```tcl puts -nonewline "Enter your name: " ``` `puts`命令用于将消息打印到终端。 `-nonewline`选项禁止换行符。 ```tcl flush stdout ``` Tcl 缓冲区在内部输出,因此用`puts`编写的字符可能不会立即出现在输出文件或设备上。 `flush`命令强制输出立即显示。 ```tcl set name [gets stdin] ``` `gets`命令从通道读取一条线。 ```tcl $ ./hello.tcl Enter your name: Jan Hello Jan ``` 脚本的示例输出。 ## `pwd`和`cd`命令 Tcl 具有`pwd`和`cd`命令,类似于 shell 命令。 `pwd`命令返回当前工作目录,`cd`命令用于更改工作目录。 ```tcl #!/usr/bin/tclsh set dir [pwd] puts $dir cd .. set dir [pwd] puts $dir ``` 在此脚本中,我们将打印当前工作目录。 然后,我们更改工作目录并再次打印工作目录。 ```tcl set dir [pwd] ``` `pwd`命令返回当前工作目录。 ```tcl cd .. ``` 我们将工作目录更改为当前目录的父目录。 我们使用`cd`命令。 ```tcl $ ./cwd.tcl /home/janbodnar/prog/tcl/io /home/janbodnar/prog/tcl ``` 样本输出。 ## `glob`命令 Tcl 具有`glob`命令,该命令返回与模式匹配的文件的名称。 ```tcl #!/usr/bin/tclsh set files [glob *.tcl] foreach file $files { puts $file } ``` 该脚本将所有带有`.tcl`扩展名的文件打印到控制台。 ```tcl set files [glob *.tcl] ``` `glob`命令返回与`*.tcl`模式匹配的文件列表。 ```tcl foreach file $files { puts $file } ``` 我们浏览文件列表,并将列表的每个项目打印到控制台。 ```tcl $ ./globcmd.tcl attributes.tcl allfiles.tcl printing.tcl hello.tcl read.tcl files.tcl globcmd.tcl write2file.tcl cwd.tcl readfile.tcl isfile.tcl addnumbers.tcl ``` 这是`globcmd.tcl`脚本的示例输出。 ## 处理文件 `file`命令操纵文件名和属性。 它有很多选择。 ```tcl #!/usr/bin/tclsh puts [file volumes] [file mkdir new] ``` 该脚本将打印系统的已安装卷,并创建一个新目录。 ```tcl puts [file volumes] ``` `file volumes`命令返回到系统上安装的卷的绝对路径。 ```tcl [file mkdir new] ``` `file mkdir`创建一个名为`new`的目录。 ```tcl $ ./voldir.tcl / $ ls -d */ doc/ new/ tmp/ ``` 在 Linux 系统上,有一个已安装的卷-根目录。 `ls`命令确认`new`目录的创建。 在下面的代码示例中,我们将检查文件名是常规文件还是目录。 ```tcl #!/usr/bin/tclsh set files [glob *] foreach fl $files { if {[file isfile $fl]} { puts "$fl is a file" } elseif { [file isdirectory $fl]} { puts "$fl is a directory" } } ``` 我们遍历当前工作目录中的所有文件名,并打印它是文件还是目录。 ```tcl set files [glob *] ``` 使用`glob`命令,我们创建当前目录的文件和目录名称的列表。 ```tcl if {[file isfile $fl]} { ``` 如果有问题的文件名是文件,我们将执行`if`命令的主体。 ```tcl } elseif { [file isdirectory $fl]} { ``` `file isdirectory`命令确定文件名是否为目录。 请注意,在 Unix 上,目录是文件的特例。 `puts`命令可用于写入文件。 ```tcl #!/usr/bin/tclsh set fp [open days w] set days {Monday Tuesday Wednesday Thursday Friday Saturday Sunday} puts $fp $days close $fp ``` 在脚本中,我们打开一个文件进行写入。 我们将一周中的几天写入文件。 ```tcl set fp [open days w] ``` 我们打开一个名为`days`的文件进行写入。 `open`命令返回一个通道 ID。 ```tcl set days {Monday Tuesday Wednesday Thursday Friday Saturday Sunday} ``` 该数据将被写入文件。 ```tcl puts $fp $days ``` 我们使用`open`命令返回的通道 ID 写入文件。 ```tcl close $fp ``` 我们关闭打开的频道。 ```tcl $ ./write2file.tcl $ cat days Monday Tuesday Wednesday Thursday Friday Saturday Sunday ``` 我们运行脚本并检查`days`文件的内容。 在下面的脚本中,我们将从文件中读取数据。 ```tcl $ cat languages Python Tcl Visual Basic Perl Java C C# Ruby Scheme ``` 我们在目录中有一个简单的文件,称为语言。 ```tcl #!/usr/bin/tclsh set fp [open languages r] set data [read $fp] puts -nonewline $data close $fp ``` 我们从提供的文件中读取数据,读取其内容,然后将数据打印到终端。 ```tcl set fp [open languages r] ``` 我们通过以只读模式打开语言文件来创建频道。 ```tcl set data [read $fp] ``` 如果我们没有为`read`命令提供第二个参数,它将从文件中读取所有数据,直到文件结尾。 ```tcl puts -nonewline $data ``` 我们将数据打印到控制台。 ```tcl $ ./readfile.tcl Python Tcl Visual Basic Perl Java C C# Ruby Scheme ``` `readfile.tcl`脚本的示例运行。 `eof`命令检查所提供通道的行尾。 ```tcl #!/usr/bin/tclsh set fp [open languages] while {![eof $fp]} { puts [gets $fp] } close $fp ``` 我们使用`eof`命令读取文件的内容。 ```tcl while {![eof $fp]} { puts [gets $fp] } ``` 循环继续进行,直到`eof`遇到文件结尾都返回`true`为止。 在体内,我们使用`gets`命令从文件中读取一行。 ```tcl $ ./readfile2.tcl Python Tcl Visual Basic Perl Java C C# Ruby Scheme ``` `readfile2.tcl`脚本的示例运行。 下一个脚本将执行一些其他文件操作。 ```tcl #!/usr/bin/tclsh set fp [open newfile w] puts $fp "this is new file" flush $fp file copy newfile newfile2 file delete newfile close $fp ``` 我们打开一个文件,并在其中写入一些文本。 文件被复制。 然后删除原始文件。 ```tcl file copy newfile newfile2 ``` `file copy`命令复制文件。 ```tcl file delete newfile ``` 原始文件用`file delete`命令删除。 在最后一个示例中,我们将使用文件属性。 ```tcl #!/usr/bin/tclsh set files [glob *] set mx 0 foreach fl $files { set len [string length $fl] if { $len > $mx} { set mx $len } } set fstr "%-$mx\s %-s" puts [format $fstr Name Size] set fstr "%-$mx\s %d bytes" foreach fl $files { set size [file size $fl] puts [format $fstr $fl $size] } ``` 该脚本将创建两列。 在第一列中,我们有文件的名称。 在第二列中,我们显示文件的大小。 ```tcl foreach fl $files { set len [string length $fl] if { $len > $mx} { set mx $len } } ``` 在此循环中,我们找出了最长的文件名。 格式化输出列时将使用此格式。 ```tcl set fstr "%-$mx\s %-s" puts [format $fstr Name Size] ``` 在这里,我们打印列的标题。 要格式化数据,我们使用`format`命令。 ```tcl set fstr "%-$mx\s %d bytes" foreach fl $files { set size [file size $fl] puts [format $fstr $fl $size] } ``` 我们遍历文件列表并打印每个文件名及其大小。 `file size`命令确定文件的大小。 ```tcl $ ./attributes.tcl Name Size attributes.tcl 337 bytes newfile2 17 bytes allfiles.tcl 75 bytes printing.tcl 83 bytes languages 51 bytes hello.tcl 109 bytes days 57 bytes read.tcl 113 bytes files.tcl 140 bytes globcmd.tcl 82 bytes write2file.tcl 134 bytes doc 4096 bytes cwd.tcl 76 bytes tmp 4096 bytes readfile.tcl 98 bytes isfile.tcl 219 bytes ``` 样品运行。 在本章中,我们介绍了 Tcl 中的输入/输出操作。