0

ファイルはメモリに収まりません。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アクセスメソッドが配列をファイルに結び付ける(配列要素ごとに1行)」の意味もよくわかりません。タイはファイルを配列に正しく読み込まないのですか?

4

1 に答える 1

4

pack N32ビット整数を作成します。最大32ビット整数は4GBであるため、これを使用して100GBのサイズのファイルにインデックスを格納することはできません。

一部のビルドは64ビット整数を使用します。それらでは、を使用できますj

一部のビルドは32ビット整数を使用します。tellそれらに浮動小数点数を返し、最大8,388,608GBのサイズのファイルにロスレスでインデックスを付けることができます。それらについては、を使用する必要がありますF

ポータブルコードは次のようになります。

use Config qw( %Config );
my $off_t = $Config{lseeksize} > $Config{ivsize} ? 'F' : 'j';

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

注:インデックスファイルは、それを構築したのと同じPerl(または、同じ整数サイズ、シークサイズ、マシンエンディアンを持つ少なくとも1つ)でのみ使用されると想定しています。その仮定が当てはまらない場合はお知らせください。

于 2012-09-27T18:13:01.747 に答える