3

我有一个名为 time.dat 和 acc.dat 的文件,它们都包含一个包含数值的列。我想从这些文件中创建包含文件中值的列表。有谁知道该怎么做?

proc ReadRecord {inFilename outFilenameT outFilenameS} {

   if [catch {open $inFilename r} inFileID] {
      puts stderr "Cannot open $inFilename for reading"
   } else {
      set outFileIDS [open $outFilenameS w]
      set outFileIDT [open $outFilenameT w]
      foreach line [split [read $inFileID] \n] {

         if {[llength $line] == 0} {
            continue
         } else {
            puts $outFileIDT [lindex $line 0]
            puts $outFileIDS [lindex $line 1]
         } 
      }
      close $outFileIDT
      close $outFileIDS
      close $inFileID
   }
};
4

3 回答 3

6

这样的事情应该可以解决问题:

proc listFromFile {filename} {
    set f [open $filename r]
    set data [split [string trim [read $f]]]
    close $f
    return $data
}
set times [listFromFile time.dat]
set accs  [listFromFile acc.dat]

[split]命令在这里为您完成“繁重的工作”。

编辑

如果您有一个包含两列的文件,并且您想从函数中返回该数据集,那么您有几个选择。两者都涉及返回“列表列表”,然后只是您想要两个包含N个元素的列表还是包含两个元素的N个列表的问题。例如,要获得两个元素的N个列表:

proc readData {filename} {
    set result {}
    set f [open $filename r]
    foreach line [split [read $f] \n] {
        lappend result $line
    }
    return $result
}

或者,要获得两个包含N个元素的列表:

proc readData {filename} {
    set times {}
    set accs  {}
    set f [open $filename r]
    foreach line [split [read $f] \n] {
        lappend times [lindex $line 0]
        lappend accs  [lindex $line 1]
    }
    return [list $times $accs]
}

从技术上讲,您甚至可以将数据作为2N个元素的列表返回:

proc readData {filename} {
    set result {}
    set f [open $filename r]
    foreach line [split [read $f] \n] {
        lappend result [lindex $line 0] [lindex $line 1]
    }
    return $result
}

这完全取决于您计划如何使用这些数据。

于 2013-08-13T22:10:16.157 回答
2

如果文件不大,并且您不介意让文件句柄保持打开状态,直到脚本退出(它将自动关闭),您可以在一行中完成所有操作

proc listFromFile {file} { return [split [read [open $file r]] "\n"] }

虽然在 \n 上拆分意味着如果最后一行有 \n (大多数情况下),你最终会在列表中得到一个额外的空元素。你可以删除它

proc listFromFile {file} { return [lreplace [split [read [open $file r]] "\n"] end end] }

最后,如果您希望列表文件有注释,即忽略以 # 开头的文件,您可以使用

proc listFromFile {file} { return [lsearch -regexp -inline -all [lreplace [split [read [open $file r]] "\n"] end end] {^[^#]}] }
于 2016-03-21T20:06:21.127 回答
1

使用fileutil这变得微不足道:

package require fileutil

fileutil::write testfile.dat {a b c}
set myList [fileutil::cat testfile.dat]
lindex $a 1

这实际上是先将一个列表写入文件,然后再读回该数据。由于 tcl 将列表表示为字符串,我们只需将文件内容分配给一个变量。

如果您的列表使用换行符作为元素分隔符,或者不是纯空白(制表符、空格),您将不得不使用split,即split [fileutil::cat testfile.dat] \n如上述帖子中所述。

注意:除了字符串表示之外,内部列表还可以使用列表表示。在列表上调用 sting 和 list 函数交替触发表示之间的转换并使其他表示无效。出于这个原因,在两者之间切换也很糟糕,但这是一个不同的主题,对于那些感兴趣的人来说,请查看tcl wiki on shimmering

于 2017-07-05T18:45:24.450 回答