2013-08-02 22 views
2

對於一些原因,我必須找到一個文件的最後一行開始,到目前爲止,我已經做到了這一點:查找文件最後一行的開始?

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) 

有什麼其他方式來做到這一點?

+0

我' d從命令行使用'tail -n 1 file' :-) – Stefan

+0

因此ruby標籤.. :) – mlemboy

回答

1

可以使用

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會引發錯誤那麼你想要的值是零,但是這個算法永遠不會找到它

  • +0

    考慮到第一次建議的代碼應該運行得有多快,我願意與它一起運行。這將是一個巨大的文件,或通過跳到底和反向工作來看到很大的改進。在文本文件中假設行長度爲80或132是非常安全的,但是CSV或TSV文件可能與此大不相同,並導致意外行爲。 –

    +0

    最後一個建議可以輕鬆,安全地快速使用1024而不是80的值。Ruby和底層操作系統應該能夠儘可能快地獲取1024個字節,而更高的數字將更快地找到答案。意外的長線。這種情況下,I/O緩衝區的大小應該非常方便。 –

    相關問題