我正在尝试编写一个脚本,将一些数据块存储在平面.txt文件中(它们是小文件,少于100行)。
无论如何,我试图实际上用一个新的值更新一行匹配行,同时将其他所有内容留在文件中,但不能完全弄清楚如何修改1行而不是更换完整行文件。
到目前为止,这是我的代码:
# get file contents as array.
array_of_lines = File.open( "textfile.txt", "r" ).readlines.map( &:chomp )
line_start = "123456:" # unique identifier
new_string = "somestring" # a new string to be put after the line_start indentifier.
# cycle through array finding the one to be updated/replaced with a new line.
# the line we're looking for is in format 123456:some old value
# delete the line matching the line_start key
array_of_lines.delete_if( |line| line_start =~ line )
# write new string into the array.
array_of_lines.push( "#{line_start}:#{new_string}" )
# write array contents back to file, replacing all previous content in the process
File.open( "textfile.txt", "w" ) do |f|
array_of_lines.each do |line|
f.puts line
end
end
textfile.txt
内容将始终由以下格式组成:
UNIQUE_ID:string_of_text
我可以使用脚本生成的应用数据来匹配unique_id
,以确定要更新的文本行。
有没有更好的方法来做我想做的事情?
将整个文件读入内存似乎有点低效,只需更新该文件中的一行就可以循环所有内容。
答案 0 :(得分:4)
除非您编写的新数据与旧数据的长度相同,否则您无法执行所需操作。
如果长度不同,则需要移动修改后文件中的所有字节。移动文件数据总是涉及重写所有内容(从修改开始)。在这种情况下,你也可以重写整个文件,因为你的文件很小。
如果替换数据的长度相同,则可以使用IO.seek
将文件指针放到适当的位置,然后使用write
输入替换数据。
如果你仍然不想重写整个文件,而只是移动数据(如果替换长度不同),那么你需要seek
到正确的位置然后{{1}从那一点开始,一切都到了文件的末尾。如果替换时间较短,您还需要调用File.truncate
来调整文件大小。