Tcl:检查两个文件之间的相同内容
Tcl: Check for same content between two files
我有一个用 vimscript 编写的程序,它检查两个文件是否相同。它对 diff
进行系统调用以验证它们是否不同。
我在 Tcl 中需要类似的东西,但不求助于外部命令或系统调用。我不需要知道文件之间的差异或进行比较,如果两个文件具有相同的内容则为 return 1,如果内容不同则为 0。
proc comp_file {file1 file2} {
# optimization: check file size first
set equal 0
if {[file size $file1] == [file size $file2]} {
set fh1 [open $file1 r]
set fh2 [open $file2 r]
set equal [string equal [read $fh1] [read $fh2]]
close $fh1
close $fh2
}
return $equal
}
if {[comp_file /tmp/foo /tmp/bar]} {
puts "files are equal"
}
对于直接的二进制比较,您可以一次只处理一个块。 (尽管您可以选择更大的值,但每个块 4kB 可能已经足够了;I/O 开销在任何情况下都将占主导地位。)最简单的表达方式是在 try
…[=14= 中使用循环](需要 Tcl 8.6):
proc sameContent {file1 file2} {
set f1 [open $file1 "rb"]
set f2 [open $file2 "rb"]
try {
while 1 {
if {[read $f1 4096] ne [read $f2 4096]} {
return 0
} elseif {[eof $f1]} {
# The same if we got to EOF at the same time
return [eof $f2]
} elseif {[eof $f2]} {
return 0
}
}
} finally {
close $f1
close $f2
}
}
否则,我们可以利用这样一个事实,即我们可以查看是否已设置变量以保持逻辑相当简单(这不太清楚)来制作适用于旧版本 Tcl 的代码:
proc sameContent {file1 file2} {
set f1 [open $file1]
fconfigure $f1 -translation binary
set f2 [open $file2]
fconfigure $f2 -translation binary
while {![info exist same]} {
if {[read $f1 4096] ne [read $f2 4096]} {
set same 0
} elseif {[eof $f1]} {
# The same if we got to EOF at the same time
set same [eof $f2]
} elseif {[eof $f2]} {
set same 0
}
}
close $f1
close $f2
return $same
}
两者的调用方式相同:
if {[sameContent "./foo.txt" "some/dir/bar.txt"]} {
puts "They're the same contents, byte-for-byte"
} else {
puts "A difference was found"
}
我有一个用 vimscript 编写的程序,它检查两个文件是否相同。它对 diff
进行系统调用以验证它们是否不同。
我在 Tcl 中需要类似的东西,但不求助于外部命令或系统调用。我不需要知道文件之间的差异或进行比较,如果两个文件具有相同的内容则为 return 1,如果内容不同则为 0。
proc comp_file {file1 file2} {
# optimization: check file size first
set equal 0
if {[file size $file1] == [file size $file2]} {
set fh1 [open $file1 r]
set fh2 [open $file2 r]
set equal [string equal [read $fh1] [read $fh2]]
close $fh1
close $fh2
}
return $equal
}
if {[comp_file /tmp/foo /tmp/bar]} {
puts "files are equal"
}
对于直接的二进制比较,您可以一次只处理一个块。 (尽管您可以选择更大的值,但每个块 4kB 可能已经足够了;I/O 开销在任何情况下都将占主导地位。)最简单的表达方式是在 try
…[=14= 中使用循环](需要 Tcl 8.6):
proc sameContent {file1 file2} {
set f1 [open $file1 "rb"]
set f2 [open $file2 "rb"]
try {
while 1 {
if {[read $f1 4096] ne [read $f2 4096]} {
return 0
} elseif {[eof $f1]} {
# The same if we got to EOF at the same time
return [eof $f2]
} elseif {[eof $f2]} {
return 0
}
}
} finally {
close $f1
close $f2
}
}
否则,我们可以利用这样一个事实,即我们可以查看是否已设置变量以保持逻辑相当简单(这不太清楚)来制作适用于旧版本 Tcl 的代码:
proc sameContent {file1 file2} {
set f1 [open $file1]
fconfigure $f1 -translation binary
set f2 [open $file2]
fconfigure $f2 -translation binary
while {![info exist same]} {
if {[read $f1 4096] ne [read $f2 4096]} {
set same 0
} elseif {[eof $f1]} {
# The same if we got to EOF at the same time
set same [eof $f2]
} elseif {[eof $f2]} {
set same 0
}
}
close $f1
close $f2
return $same
}
两者的调用方式相同:
if {[sameContent "./foo.txt" "some/dir/bar.txt"]} {
puts "They're the same contents, byte-for-byte"
} else {
puts "A difference was found"
}