是否有可能从最后返回x行文件的函数?该函数将采用参数定义我们想要读取的距离(在行测量中)以及我们希望从该位置返回多少行:
get_lines_file_end(IoDevice, LineNumberPositionFromEnd, LineCount) ->
实施例: 我们有30行0-29的文件
get_lines_file_end(IoDevice, -10, 10) // will return lines 20-29
get_lines_file_end(IoDevice, -20, 10) // will return lines 10-19
这个问题是我只能通过一定数量的字节来寻找文件:位置。
目的: 从上一页"页面"开始以页面方式查看大型日志文件(数百MB)。 Erlang用于javascript web使用的rest api。
此功能的用法是逐页查看整个日志文件,其中页面由x行文本表示。不需要处理日志文件或获取某些信息。
由于
答案 0 :(得分:2)
要提出两点:
file:position/2
来直接跳转到您需要的位。要构建有关文件的元数据,您需要执行类似于以下操作的内容:
1> {ok, Data} = file:read_file("TheLongDarkTeaTimeOfTheSoul.txt").
{ok,<<"Douglas Adams. The Long Dark Tea-Time of the Soul\r\n\r\n"...>>}
2> LineEnds = binary:matches(Data, <<"\r\n">>).
[{49,2},
{51,2},
{53,2},
{...}|...]
然后将LineEnds
分别保存为文件本身的元数据。在文件数据中使用此搜索是基本的(如使用file:position/2
,其中数据在换行符X处,或length(LineEnds) - X
或其他任何内容。
但这仍然很愚蠢。
如果你想在日志文件中跳转,特别是如果你想能够找到它们中的模式,计算它们的某些方面等等,那么你几乎肯定会更好地将它们读入像Postgres这样的数据库中按行,计算行数。那时,分页成为一个微不足道的问题。
但是,日志文件通常充满了最符合符号而非实际文本的数据,并且标记日志文件可能更好。考虑访问日志文件的情况。重复数量的访问者从有限数量的接入点(IP,设备或其他)访问任意次数。可以在数据库中单独索引和比较而非简单的每个方面。标记化本身也是微不足道的。在以后的数据分析方面,这个解决方案不仅更多更快,而且它自然有助于回答非常困难来回答有关数据内容的问题以非常直率和熟悉的方式。 ......你甚至不必丢失任何原始数据或处理的中间阶段(可能以不同的方式独立使用)。另外......请注意,上述所有工作都可以在Erlang中轻松实现。无论您的计算资源情况如何,编写最能充分利用硬件的解决方案当然都在掌握之中(假设您有足够的总数据,这甚至是一个问题)。
就像很多“如何用数据Y做X?”问题,真正的答案总是围绕“你对数据的目标是什么以及为什么?”
答案 1 :(得分:0)
您可以使用file:read_line/1
function读取行,丢弃与您的范围不匹配的行:
get_lines(File, From) when From > 0 ->
get_lines(File, file:read_line(File), From, 1).
get_lines(_File, eof, _From, _Current) ->
[];
get_lines(File, {ok, _Line}, From, Current) when Current < From ->
get_lines(File, file:read_line(File), From, Current + 1);
get_lines(File, {ok, Line}, From, Current) ->
[Line|get_lines(File, file:read_line(File), From, Current + 1)];
get_lines(_IoDevice, Error, _From, _Current) ->
Error.