如何读取 Rails 中的文件块而不从头开始再次读取
How to read a file block in Rails without read it again from beginning
我有一个不断增长的文件(日志),我需要按块读取。
我通过 Ajax 拨打电话以获得指定数量的线路。
我使用 File.foreach 来读取我想要的行,但它总是从头开始读取,我只需要直接 return 我想要的行。
示例伪代码:
#First call:
File.open and return 0 to 10 lines
#Second call:
File.open and return 11 to 20 lines
#Third call:
File.open and return 21 to 30 lines
#And so on...
有办法做这个吗?
解决方案 1:读取整个文件
此处建议的解决方案:
.. 在您的情况下不是一个有效的解决方案,因为它要求您为每个 AJAX 请求读取文件中的所有行,即使您只需要日志文件的最后 10 行。
这是对时间的极大浪费,在计算方面,求解时间(即以大小为 N 的块处理整个日志文件)接近指数求解时间。
解法二:求
由于您的 AJAX 调用请求顺序行,我们可以通过 在读取 之前寻找正确的位置,使用 IO.seek
and IO.pos
来实现更有效的方法。
这需要您 return 一些额外的数据(最后一个文件位置)返回给 AJAX 客户端,同时 return 请求的行。
AJAX 请求然后成为这种形式的函数调用 request_lines(position, line_count)
,它使服务器能够 IO.seek(position)
在读取请求的行数之前。
这是解决方案的伪代码:
客户代码:
LINE_COUNT = 10
pos = 0
loop {
data = server.request_lines(pos, LINE_COUNT)
display_lines(data.lines)
pos = data.pos
break if pos == -1 # Reached end of file
}
服务器代码:
def request_lines(pos, line_count)
file = File.open('logfile')
# Seek to requested position
file.seek(pos)
# Read the requested count of lines while checking for EOF
lines = count.times.map { file.readline if !file.eof? }.compact
# Mark pos with -1 if we reached EOF during reading
pos = file.eof? ? -1 : file.pos
f.close
# Return data
data = { lines: lines, pos: pos }
end
我有一个不断增长的文件(日志),我需要按块读取。 我通过 Ajax 拨打电话以获得指定数量的线路。 我使用 File.foreach 来读取我想要的行,但它总是从头开始读取,我只需要直接 return 我想要的行。
示例伪代码:
#First call:
File.open and return 0 to 10 lines
#Second call:
File.open and return 11 to 20 lines
#Third call:
File.open and return 21 to 30 lines
#And so on...
有办法做这个吗?
解决方案 1:读取整个文件
此处建议的解决方案:
.. 在您的情况下不是一个有效的解决方案,因为它要求您为每个 AJAX 请求读取文件中的所有行,即使您只需要日志文件的最后 10 行。
这是对时间的极大浪费,在计算方面,求解时间(即以大小为 N 的块处理整个日志文件)接近指数求解时间。
解法二:求
由于您的 AJAX 调用请求顺序行,我们可以通过 在读取 之前寻找正确的位置,使用 IO.seek
and IO.pos
来实现更有效的方法。
这需要您 return 一些额外的数据(最后一个文件位置)返回给 AJAX 客户端,同时 return 请求的行。
AJAX 请求然后成为这种形式的函数调用 request_lines(position, line_count)
,它使服务器能够 IO.seek(position)
在读取请求的行数之前。
这是解决方案的伪代码:
客户代码:
LINE_COUNT = 10
pos = 0
loop {
data = server.request_lines(pos, LINE_COUNT)
display_lines(data.lines)
pos = data.pos
break if pos == -1 # Reached end of file
}
服务器代码:
def request_lines(pos, line_count)
file = File.open('logfile')
# Seek to requested position
file.seek(pos)
# Read the requested count of lines while checking for EOF
lines = count.times.map { file.readline if !file.eof? }.compact
# Mark pos with -1 if we reached EOF during reading
pos = file.eof? ? -1 : file.pos
f.close
# Return data
data = { lines: lines, pos: pos }
end