【问题标题】:How to look for the difference between two large files in tcl?如何在tcl中查找两个大文件之间的区别?
【发布时间】:2014-06-15 12:13:43
【问题描述】:
我有两个文件,其中的一些内容可能在这两个文件中是通用的。 (比如说文件A.txt和文件B.txt)
这两个文件都是排序文件。
我需要得到文件A.txt和B.txt的区别,即一个文件C.txt,除了两者的共同内容外,其内容都是A。
我使用了典型的搜索和打印算法,即从A.txt 中取出一行,在B.txt 中搜索,如果找到,则在C.txt 中不打印任何内容,否则在C.txt 中打印该行。
但是,我正在处理包含大量内容的文件,因此会引发错误:failed to load too many files。 (虽然它适用于较小的文件)
任何人都可以提出更有效的获取C.txt 的方法吗?
要使用的脚本:仅限 TCL!
【问题讨论】:
-
你的“仅限 tcl”限制太糟糕了:这正是 comm 的用途。
标签:
file
file-io
compare
tcl
【解决方案1】:
首先,too many files 错误表明您没有关闭通道,可能在B.txt 扫描仪中。解决这个问题可能是您的第一个目标。如果你有 Tcl 8.6,试试这个帮助程序:
proc scanForLine {searchLine filename} {
set f [open $filename]
try {
while {[gets $f line] >= 0} {
if {$line eq $searchLine} {
return true
}
}
return false
} finally {
close $f
}
}
但是,如果其中一个文件足够小以合理地放入内存中,则最好将其读入哈希表(例如字典或数组):
set f [open B.txt]
while {[gets $f line]} {
set B($line) "any dummy value; we'll ignore it"
}
close $f
set in [open A.txt]
set out [open C.txt w]
while {[gets $in line]} {
if {![info exists B($line)]} {
puts $out $line
}
}
close $in
close $out
这要高效得多,但取决于B.txt 是否足够小。
如果A.txt 和B.txt 都太大了,您最好分阶段进行某种处理,在中间将内容写入磁盘。这变得相当复杂!
set filter [open B.txt]
set fromFile A.txt
for {set tmp 0} {![eof $filter]} {incr tmp} {
# Filter by a million lines at a time; that'll probably fit OK
for {set i 0} {$i < 1000000} {incr i} {
if {[gets $filter line] < 0} break
set B($line) "dummy"
}
# Do the filtering
if {$tmp} {set fromFile $toFile}
set from [open $fromFile]
set to [open [set toFile /tmp/[pid]_$tmp.txt] w]
while {[gets $from line] >= 0} {
if {![info exists B($line)]} {
puts $to $line
}
}
close $from
close $to
# Keep control of temporary files and data
if {$tmp} {file delete $fromFile}
unset B
}
close $filter
file rename $toFile C.txt
警告!我没有测试过这段代码……