저는 Rails 앱의 로그 뷰어에서 작업 중이며 기본 위에서 아래로가 아니라 아래에서 위로 로그 파일을 200 줄 정도 읽어야한다는 것을 알고 있습니다.Ruby에서 파일을 아래에서 위로 읽는 방법?
로그 파일이 상당히 커질 수 있으므로 이미 IO.readlines ("log_file.log") [- 200 ..- 1] 방법을 시도하고 배제했습니다.
플러그인이나 보석없이 루비에서 파일을 거꾸로 읽는 다른 방법이 있습니까?
저는 Rails 앱의 로그 뷰어에서 작업 중이며 기본 위에서 아래로가 아니라 아래에서 위로 로그 파일을 200 줄 정도 읽어야한다는 것을 알고 있습니다.Ruby에서 파일을 아래에서 위로 읽는 방법?
로그 파일이 상당히 커질 수 있으므로 이미 IO.readlines ("log_file.log") [- 200 ..- 1] 방법을 시도하고 배제했습니다.
플러그인이나 보석없이 루비에서 파일을 거꾸로 읽는 다른 방법이 있습니까?
엄청난 파일에서도 작동하는 유일한 방법은 끝까지 한 번에 n 바이트를 읽는 것입니다. 이것은 본질적으로 Unix tail
의 작동 방식입니다.
Array
로 지난 n
라인 반환 IO#tail(n)
의 예 구현 :
class IO
TAIL_BUF_LENGTH = 1 << 16
def tail(n)
return [] if n < 1
seek -TAIL_BUF_LENGTH, SEEK_END
buf = ""
while buf.count("\n") <= n
buf = read(TAIL_BUF_LENGTH) + buf
seek 2 * -TAIL_BUF_LENGTH, SEEK_CUR
end
buf.split("\n")[-n..-1]
end
end
구현은 조금 순진,하지만 빠른 벤치 마크는 말도 안되는 차이가이 간단한 구현은 이미 할 수있는 것을 보여줍니다 (
user system total real
f.readlines[-200..-1] 7.150000 1.150000 8.300000 ( 8.297671)
f.tail(200) 0.000000 0.000000 0.000000 ( 0.000367)
벤치 마크 코드 :
,691yes > yes.txt
으로 생성 된 ~ 25메가바이트 파일) 테스트
require "benchmark"
FILE = "yes.txt"
Benchmark.bmbm do |b|
b.report "f.readlines[-200..-1]" do
File.open(FILE) do |f|
f.readlines[-200..-1]
end
end
b.report "f.tail(200)" do
File.open(FILE) do |f|
f.tail(200)
end
end
end
물론 other implementations이 이미 있습니다. 나는 아무 것도 시도하지 않았으므로 나는 최선의 것을 말할 수 없다.
말인지 생각'TAIL_BUF_LENGTH = 2 ** 16' 또는'1 << 16'이며, 둘 다 '65536' (64Ki)로 평가됩니다. '2^16'은 binary exclusive-or이고'18'으로 평가됩니다. –
위대한 작품! 벤치 마크상의 차이점은 readlines와 비교하면 미친 것입니다. 결과 배열의 각 줄에 해당 줄 번호를 출력 할 수 있습니까? 감사합니다. – ericalli
@ two2twelve : 아니에요. 이 전체 연습의 * 전체 목적 *은 "아래에서 위로"라는 파일을 읽는 것입니다. (당신의 말이 아닌, 나의 것이지요.) 당신이 * bottom *에서 시작했다면, 당신은 당신이 어떤 라인 (파일의 상단 *에서부터 계산됩니다)을 알 수 있습니까? 아니면 밑바닥부터 세는 것을 의미 했습니까? 이 경우 버퍼에서 인덱스 i의 라인은 아래에서 n-i 번째 라인입니다. –
파일을 효율적으로 줄 단위로 읽는 모듈 Elif (Perl의 File::ReadBackwards 포트)이 있습니다.
나는 몹시 멋진 답변에 대해 언급하기에는 너무 새롭기 때문에 별도의 답변으로 게시해야합니다. 로그 파일이 기록되는 동안이 기능을 사용하여 로그의 마지막 부분에 완료되었음을 알리는 문자열이 포함되어 있으며 파싱을 시작할 수 있습니다.
따라서 작은 파일을 처리하는 것이 중요합니다 (로그가 작을 때 핑할 수도 있음). 의
class IO
def tail(n)
return [] if n < 1
if File.size(self) < (1 << 16)
tail_buf_length = File.size(self)
return self.readlines.reverse[0..n-1]
else
tail_buf_length = 1 << 16
end
self.seek(-tail_buf_length,IO::SEEK_END)
out = ""
count = 0
while count <= n
buf = self.read(tail_buf_length)
count += buf.count("\n")
out += buf
# 2 * since the pointer is a the end , of the previous iteration
self.seek(2 * -tail_buf_length,IO::SEEK_CUR)
end
return out.split("\n")[-n..-1]
end
end
중복 : 그래서 내가 molf 코드 강화 [? 루비에서 파일의 마지막 n 줄을 읽기] (http://stackoverflow.com/questions/754494) – hippietrail