戻るなら負数を指定します。
io.seek(-lines, IO::SEEK_END)
ただ、バイト単位なので、tail -c
相当ですね。
行単位にするなら、
案1:
先頭から順番に行を認識しながら読んで、直近のlines
行を保存しつつ、最後まで読んで保存したものを表示
案2:
末尾から1バイトずつ遡って読んでいき(毎回seek
する)、lines
個目の改行を認識して、読んだ物を表示
案3:
その折衷案
#追記
質問追記に対しての改善。
1.末尾のバイトが欠ける、および、表示が\n
から始まる点の対応
Ruby
1def tail(lines, filename)
2 File.open(filename) do |io|
3 chars_array = []
4
5 io.seek(-1, IO::SEEK_END)
6 while chars_array.count("\n") < lines+1
7 chars_array << io.read(1)
8 io.seek(-2, IO::SEEK_CUR)
9 end
10 chars_array.pop
11
12 p chars_array.reverse.join
13 end
14end
2.さらに、大きすぎる行数を指定した場合の対応
Ruby
1def tail(lines, filename)
2 File.open(filename) do |io|
3 chars_array = []
4
5 io.seek(-1, IO::SEEK_END)
6 while chars_array.count("\n") < lines+1
7 chars_array << io.read(1)
8 if io.pos == 1
9 chars_array << :DUMMY
10 break
11 end
12 io.seek(-2, IO::SEEK_CUR)
13 end
14 chars_array.pop
15
16 p chars_array.reverse.join
17 end
18end
3.最終行の末尾に\n
が無いケースと、大きさゼロのファイルの対応
あわせて、少しスッキリさせる。
Ruby
1def tail(lines, filename)
2 File.open(filename) do |io|
3 io.seek(-1, IO::SEEK_END) rescue nil
4 chars_array = [io.read(1)]
5 n = 0
6 while io.pos >= 2 # 普通の「EOFでない間」に相当
7 io.seek(-2, IO::SEEK_CUR)
8 c = io.read(1)
9 if c == "\n"
10 n += 1
11 break if n >= lines
12 end
13 chars_array << c
14 end
15
16 p chars_array.reverse.join
17 end
18end
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2020/12/20 02:57 編集
2020/12/20 06:28
退会済みユーザー
2020/12/20 06:40
退会済みユーザー
2020/12/20 08:28
退会済みユーザー
2020/12/20 11:08
2020/12/20 11:29 編集
退会済みユーザー
2020/12/20 11:52
2020/12/20 11:58 編集
退会済みユーザー
2020/12/20 12:28