對於一些原因,我必須找到一個文件的最後一行開始,到目前爲止,我已經做到了這一點:查找文件最後一行的開始?
file.seek(-1,IO::SEEK_END)
while file.getc != "\n"
file.seek(-2,IO::SEEK_CUR)
end
這是另一種方式,但要慢得多:
buff = file.readlines
file.seek(-(buff.pop).length,IO::SEEK_END)
有什麼其他方式來做到這一點?
對於一些原因,我必須找到一個文件的最後一行開始,到目前爲止,我已經做到了這一點:查找文件最後一行的開始?
file.seek(-1,IO::SEEK_END)
while file.getc != "\n"
file.seek(-2,IO::SEEK_CUR)
end
這是另一種方式,但要慢得多:
buff = file.readlines
file.seek(-(buff.pop).length,IO::SEEK_END)
有什麼其他方式來做到這一點?
可以使用
offsets = f.each.map { f.tell }
找到文件中的所有行的端部的位置,並明確最後一行的開頭是倒數第二行的末端,即offsets[-2]
。
所以加快了一點東西,所有你需要做的是首先要seek
足夠遠,你是勢必已經沒了往日的最後一行的開頭,結尾,然後得到的名單同樣的方式。
假設你的線路都保證在長度上重量不超過80個字符:
open('myfile') do |f|
f.seek(-80, IO::SEEK_END)
offsets = f.each.map { f.tell }
puts offsets[-2]
end
或者,如果你不是很瞭解你的文件中的線的長度,你可以重複,直到你找到你已經捕獲了兩個或更多行結尾。此代碼從文件末尾逐步回退80個字符,直到offsets
有兩個或多個條目。
open('myfile') do |f|
start = 0
offsets = []
loop do
start -= 80
f.seek(start, IO::SEEK_END)
offsets = f.each.map { f.tell }
break if offsets.size >= 2
end
puts offsets[-2]
end
注意,有一些特殊的邊界情況:如果你試圖尋求脫檔
的開始。如果你的文件只有一個
IO
會引發錯誤那麼你想要的值是零,但是這個算法永遠不會找到它
考慮到第一次建議的代碼應該運行得有多快,我願意與它一起運行。這將是一個巨大的文件,或通過跳到底和反向工作來看到很大的改進。在文本文件中假設行長度爲80或132是非常安全的,但是CSV或TSV文件可能與此大不相同,並導致意外行爲。 –
最後一個建議可以輕鬆,安全地快速使用1024而不是80的值。Ruby和底層操作系統應該能夠儘可能快地獲取1024個字節,而更高的數字將更快地找到答案。意外的長線。這種情況下,I/O緩衝區的大小應該非常方便。 –
我' d從命令行使用'tail -n 1 file' :-) – Stefan
因此ruby標籤.. :) – mlemboy