Skip to content

Instantly share code, notes, and snippets.

@shaiguitar
Last active July 22, 2016 09:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save shaiguitar/6d926587e98fc8a5e301 to your computer and use it in GitHub Desktop.
Save shaiguitar/6d926587e98fc8a5e301 to your computer and use it in GitHub Desktop.
tail in ruby
class Tail
class << self
def tail(path, n)
file = File.open(path, "r")
buffer_s = 512
line_count = 0
file.seek(0, IO::SEEK_END)
offset = file.pos # we start at the end
while line_count <= n && offset > 0
to_read = if (offset - buffer_s) < 0
offset
else
buffer_s
end
file.seek(offset-to_read)
data = file.read(to_read)
data.reverse.each_char do |c|
if line_count > n
offset += 1
break
end
offset -= 1
if c == "\n"
line_count += 1
end
end
end
file.seek(offset)
data = file.read
end
end
end
require "minitest/autorun"
class TestTail < Minitest::Test
TEST_PATH = "/tmp/test-tail"
def setup
@file = File.open(TEST_PATH, "w")
end
def text_from(i,j)
out = ""
i.upto(j) do |x|
out << "line #{x}\n"
end
out
end
def test_empty_file
@file.write("") && @file.close
assert_equal "", Tail.tail(TEST_PATH, 10)
end
def test_smaller_line_count
@file.write(text_from(0,3)) && @file.close
assert_equal text_from(0,3), Tail.tail(TEST_PATH, 10)
end
def test_same_line_count
@file.write(text_from(0,9)) && @file.close
assert_equal text_from(0,9), Tail.tail(TEST_PATH, 10)
end
def test_larger_line_count
@file.write(text_from(0,12)) && @file.close
assert_equal text_from(3,12), Tail.tail(TEST_PATH, 10)
end
def test_very_long_lines
long_line = ("apples and oranges" * 1000) + "\n"
bunch_of_long_lines = long_line * 12
@file.write(bunch_of_long_lines) && @file.close
assert_equal (long_line * 10), Tail.tail(TEST_PATH, 10)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment