erlang从文件末尾的位置列出行

erlang从文件末尾的位置列出行,erlang,Erlang,有没有可能有一个函数从末尾返回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, -

有没有可能有一个函数从末尾返回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
这里的问题是,我只能用file:position按一定的字节数进行搜索

目的: 从最后一个“页面”开始,以页面方式查看大型日志文件(数百MB)。 Erlang用于javascript web使用的RESTAPI

该函数的用途是逐页查看整个日志文件,其中页面由x行文本表示。不需要处理日志文件,也不需要获取日志文件的某些信息

谢谢

您可以使用读取行,丢弃与您的范围不匹配的行:

From>0->
获取行(文件,文件:读取行(文件),从,1)。
获取行(\u文件、eof、\u来源、\u当前)->
[];
当当前<从->时,获取_行(文件,{ok,_行},从,当前)
获取行(文件,文件:读取行(文件),从,当前+1);
获取_行(文件,{ok,Line},From,Current)->
[行|获取行(文件,文件:读取行(文件),从,当前+1)];
获取线路(IoDevice、Error、From、Current)->
错误。
您可以使用读取行,丢弃与您的范围不匹配的行:

From>0->
获取行(文件,文件:读取行(文件),从,1)。
获取行(\u文件、eof、\u来源、\u当前)->
[];
当当前<从->时,获取_行(文件,{ok,_行},从,当前)
获取行(文件,文件:读取行(文件),从,当前+1);
获取_行(文件,{ok,Line},From,Current)->
[行|获取行(文件,文件:读取行(文件),从,当前+1)];
获取线路(IoDevice、Error、From、Current)->
错误。
您可以使用读取行,丢弃与您的范围不匹配的行:

From>0->
获取行(文件,文件:读取行(文件),从,1)。
获取行(\u文件、eof、\u来源、\u当前)->
[];
当当前<从->时,获取_行(文件,{ok,_行},从,当前)
获取行(文件,文件:读取行(文件),从,当前+1);
获取_行(文件,{ok,Line},From,Current)->
[行|获取行(文件,文件:读取行(文件),从,当前+1)];
获取线路(IoDevice、Error、From、Current)->
错误。
您可以使用读取行,丢弃与您的范围不匹配的行:

From>0->
获取行(文件,文件:读取行(文件),从,1)。
获取行(\u文件、eof、\u来源、\u当前)->
[];
当当前<从->时,获取_行(文件,{ok,_行},从,当前)
获取行(文件,文件:读取行(文件),从,当前+1);
获取_行(文件,{ok,Line},From,Current)->
[行|获取行(文件,文件:读取行(文件),从,当前+1)];
获取线路(IoDevice、Error、From、Current)->
错误。
需要指出两点:

  • 为了提高效率,您必须创建有关文本文件内容的元数据,以分摊所涉及的工作。这样,您可以在创建此元数据后,通过使用
    file:position/2
    查找,直接跳到所需的位
  • 如果这是您的用例,那么您应该以不同的方式对工作进行分区。巨大的文本文件应该被分解成更小的文本文件,或者(更有可能)你根本不应该使用文本文件。根据你的目标(你没有提到;我强烈怀疑这是一个X-Y问题),你可能根本不想要文本,而是想要知道文本所代表的东西。将原始文本保留在某个地方以防万一可能是一个好主意,但对于数据的实际处理来说,创建符号数据(更简单地说)是一个更好的主意,它表示您对数据感兴趣的内容,并将其存储在一个数据库中,在该数据库中查找、扫描、,索引和做任何你可能想做的事情都是自然的操作
  • 要构建有关文件的元数据,您需要执行类似以下操作:

    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},
     {...}|...]
    
    1>{ok,Data}=file:read_文件(“thelongdarkteatimeofsoul.txt”)。
    {好的,}
    2> LineEnds=binary:匹配(数据,)。
    [{49,2},
    {51,2},
    {53,2},
    {...}|...]
    
    然后将
    LineEnds
    另存为文件本身的meta。在文件数据中使用此搜索是基本的(如中所示,使用
    file:position/2
    ,数据位于换行符X或
    length(LineEnds)-X
    或其他位置)

    但这仍然是愚蠢的

    如果您想在日志文件中四处跳跃,特别是如果您想能够在日志文件中找到模式,计算模式的某些方面,等等,那么您几乎可以肯定会更好地将它们逐行读取到数据库中,如Postgres,边走边计算行号。在这一点上,分页成为一个微不足道的问题

    然而,日志文件通常充满了最好用符号来表示的数据,而不是实际的文本,因此对日志文件进行标记可能是更好的方法。考虑访问日志文件的情况。从有限数量的接入点(IP、设备或其他)重复访问任意次数的访问者。这方面的每个方面都可以在数据库中单独索引和比较。标记化本身也相当简单。这种解决方案不仅在以后对数据进行分析时要快得多,而且还能够自然地以非常直截了当和熟悉的方式回答关于数据内容的问题。。。而且您甚至不必丢失任何原始数据或处理的中间阶段(它们可能以不同的方式独立使用)

    还有。。。请注意,上述所有工作都可以在Erlang中非常轻松地并行进行