在一个非常大的文件中逐行读取特定的行

Posted

技术标签:

【中文标题】在一个非常大的文件中逐行读取特定的行【英文标题】:Reading a particular line by line number in a very large file 【发布时间】:2012-09-27 18:06:13 【问题描述】:

文件不适合内存。它超过 100GB,我想按行号访问特定行。在到达之前我不想逐行数数。

我已阅读http://docstore.mik.ua/orelly/perl/cookbook/ch08_09.htm

当我使用以下方法构建索引时,行返回工作到某个点。一旦行号非常大,返回的行是相同的。当我转到文件中的特定行时,将返回同一行。它似乎适用于第 1 行到第 350000 行(大约);

 # usage: build_index(*DATA_HANDLE, *INDEX_HANDLE) 
    sub build_index 
        my $data_file  = shift;
        my $index_file = shift;
        my $offset     = 0;

        while (<$data_file>) 
            print $index_file pack("N", $offset);
            $offset = tell($data_file);
        
    

    # usage: line_with_index(*DATA_HANDLE, *INDEX_HANDLE, $LINE_NUMBER)
    # returns line or undef if LINE_NUMBER was out of range
    sub line_with_index 
        my $data_file   = shift;
        my $index_file  = shift;
        my $line_number = shift;

        my $size;               # size of an index entry
        my $i_offset;           # offset into the index of the entry
        my $entry;              # index entry
        my $d_offset;           # offset into the data file

        $size = length(pack("N", 0));
        $i_offset = $size * ($line_number-1);
        seek($index_file, $i_offset, 0) or return;
        read($index_file, $entry, $size);
        $d_offset = unpack("N", $entry);
        seek($data_file, $d_offset, 0);
        return scalar(<$data_file>);
    

我也尝试过使用 DB_file 方法,但似乎需要很长时间才能打成平手。我也不太明白“DB_RECNO 访问方法将数组绑定到文件,每个数组元素一行”的含义。 tie不把文件读入数组正确吗?

【问题讨论】:

固定或可变长度行? 我不想逐行计算,直到我到达它 - 如果它们是可变长度的行,你别无选择。 听起来你会从使用数据库而不是文件中受益。 【参考方案1】:

pack N 创建一个 32 位整数。最大 32 位整数为 4GB,因此无法将索引存储到 100GB 大小的文件中。

某些版本使用 64 位整数。在这些上,您可以使用j

某些版本使用 32 位整数。 tell 返回一个浮点数,允许您无损地索引最大 8,388,608 GB 的文件。对于那些,你应该使用F

可移植代码如下所示:

use Config qw( %Config );
my $off_t = $Configlseeksize > $Configivsize ? 'F' : 'j';

...
print $index_file pack($off_t, $offset);
...

注意:我假设索引文件仅由构建它的同一个 Perl 使用(或至少一个具有相同整数大小、查找大小和机器字节序的 Perl)。如果这个假设对你不成立,请告诉我。

【讨论】:

不支持 Q。给出错误:buildIndex.pl 第 21 行, 第 1 行的包中的类型“Q”无效。 是的,索引文件只能与构建它的 Perl 一起使用。我不太了解可移植代码或如何处理它。我是 perl 的新手。我只是把所有的“N”都改成“j”还是“F”? 它会检查您的 Perl 是如何配置为生成正确的格式的。使用$off_t 而不是"N"。在你的情况下,它将是F

以上是关于在一个非常大的文件中逐行读取特定的行的主要内容,如果未能解决你的问题,请参考以下文章

在python中逐行读取一个大的压缩文本文件

如何在目标c中逐行解析JSON文件

在 C# 中逐行读取文件

在 Fortran 中逐行读取逗号分隔的文本文件

从文件中逐行读取并存储到二维数组中

在python中逐行迭代一个大的.xz文件