我正在为Google编写一个小解析器,我不确定设计它的最佳方法是什么。主要问题是它将记住它停止的位置的方式。
在解析期间,它会将新搜索附加到文件的末尾,并使用第一行浏览文件startig。现在我想这样做,如果由于某种原因执行被中断,脚本知道它已成功完成的最后一次搜索。
一种方法是在获取文件后删除文件中的一行,但在这种情况下,我必须处理线程访问文件和删除文件中第一行的顺序无法有效处理。
另一种方法是将使用过的行数写入文本文件,并跳过编号在该文件中的行。或者我可能应该使用一些数据库? TIA
答案 0 :(得分:0)
使用状态文件没有任何问题。唯一的问题是,在程序进入可能被中断的部分之前,您需要确保已完全提交对状态文件的更改。通常,这是通过IO#flush调用完成的。
例如,这是一个简单的状态跟踪类,它逐行工作:
class ProgressTracker
def initialize(filename)
@filename = filename
@file = open(@filename)
@state_filename = File.expand_path(".#{File.basename(@filename)}.position", File.dirname(@filename))
if (File.exist?(@state_filename))
@state_file = open(@state_filename, File::RDWR)
resume!
else
@state_file = open(@state_filename, File::RDWR | File::CREAT)
end
end
def each_line
@file.each_line do |line|
mark_position!
yield(line) if (block_given?)
end
end
protected
def mark_position!
@state_file.rewind
@state_file.puts(@file.pos)
@state_file.flush
end
def resume!
if (position = @state_file.readline)
@file.seek(position.to_i)
end
end
end
您可以将其与类似IO的块调用一起使用:
test = ProgressTracker.new(__FILE__)
n = 0
test.each_line do |line|
n += 1
puts "%3d %s" % [ n, line ]
if (n == 10)
raise 'terminate'
end
end
在这种情况下,程序会自行读取并在由于模拟错误而在十行之后停止。在第二次运行时,它应该显示接下来的十行,如果有那么多,或者只是在没有要检索的其他数据的情况下退出。
需要注意的是,如果要重新处理文件,或者文件已重置,则需要删除与输入数据关联的.position文件。也无法编辑文件并删除较早的行,否则会丢失偏移量跟踪。只要您只是将数据附加到文件或重新启动它,一切都会没问题。