Как я могу установить считанный из файла размер буфера в Perl для оптимизации его для больших файлов?

VBA (включая IDE MS Office):

1) Плохая Документация
2) Плохие сообщения об ошибках
3) Несоответствующие Стандартные программы Управления Массивом
4) Необходимость повторить типы для операторов DIM
5) не распечатает в цвете (должны купить стороннее дополнение)

6
задан brian d foy 10 August 2009 в 09:40
поделиться

3 ответа

Вы можете повлиять на буферизацию, если вы работаете в ОС, поддерживающей setvbuf ; см. документацию для IO :: Handle .

Если вы используете perl v5.10 или новее, в этом нет необходимости для явного создания объекта IO :: Handle , как описано в документации, поскольку все дескрипторы файлов неявно добавляются к объектам IO :: Handle , начиная с этого выпуска.

use 5.010;
use strict;
use warnings;

use autodie;

use IO::Handle '_IOLBF';

open my $handle, '<:utf8', 'foo';

my $buffer;
$handle->setvbuf($buffer, _IOLBF, 0x10000);

while ( my $line = <$handle> ) {
    ...
}
7
ответ дан 10 December 2019 в 00:42
поделиться

Нет, нет (за исключением перекомпиляции модифицированного perl), но вы можете прочитать весь файл в памяти, а затем работать построчно из него:

use File::Slurp;
my $buffer = read_file("filename");
open my $in_handle, "<", \$buffer;
while ( my $line = readline($in_handle) ) {
}

Обратите внимание, что perl до 5.10 по умолчанию использовать буферы stdio в большинстве мест (но часто обман и доступ к буферам напрямую, а не через библиотеку stdio), но в 5.10 и более поздних версий по умолчанию используется собственная система слоев Perlio. Последний, похоже, использует 4к буфер по умолчанию, но написание слоя, позволяющего его настраивать, должно быть тривиальным (как только вы поймете, как написать слой: см. perldoc perliol ).

2
ответ дан 10 December 2019 в 00:42
поделиться

Предупреждение, следующий код прошел лишь легкое тестирование. Приведенный ниже код - это первый снимок функции, которая позволит вам обрабатывать файл построчно (отсюда и название функции) с размером буфера, определяемым пользователем. Требуется до четырех аргументов:

  1. дескриптор открытого файла (по умолчанию STDIN )
  2. размер буфера (по умолчанию 4 КБ)
  3. ссылка на переменную для сохранения строки (по умолчанию это $ _ )
  4. анонимная подпрограмма для вызова файла (по умолчанию выводится строка).

Аргументы позиционны, за исключением того, что последний аргумент всегда может быть анонимной подпрограммой. Строки обрабатываются автоматически.

Возможные ошибки:

  • может не работать в системах, где перевод строки является символом конца строки.
  • , скорее всего, не сработает при сочетании с лексическим $ _ (введенным в Perl 5.10)

Вы можете видеть из strace , что он читает файл с указанным размером буфера. Если мне нравится, как проходит тестирование, вы можете вскоре увидеть это на CPAN .

#!/usr/bin/perl

use strict;
use warnings;
use Scalar::Util qw/reftype/;
use Carp;

sub line_by_line {
    local $_;
    my @args = \(
        my $fh      = \*STDIN,
        my $bufsize = 4*1024,
        my $ref     = \$_,
        my $coderef = sub { print "$_\n" },
    );
    croak "bad number of arguments" if @_ > @args;

    for my $arg_val (@_) {
        if (reftype $arg_val eq "CODE") {
            ${$args[-1]} = $arg_val;
            last;
        }
        my $arg = shift @args;
        $$arg = $arg_val;
    }

    my $buf;
    my $overflow ='';
    OUTER:
    while(sysread $fh, $buf, $bufsize) {
        my @lines = split /(\n)/, $buf;
        while (@lines) {
            my $line  = $overflow . shift @lines;
            unless (defined $lines[0]) {
                $overflow = $line;
                next OUTER;
            }
            $overflow = shift @lines;
            if ($overflow eq "\n") {
                $overflow = "";
            } else {
                next OUTER;
            }
            $$ref = $line;
            $coderef->();
        }
    }
    if (length $overflow) {
        $$ref = $overflow;
        $coderef->();
    }
}

my $bufsize = shift;

open my $fh, "<", $0
    or die "could not open $0: $!";

my $count;
line_by_line $fh, sub {
    $count++ if /lines/;
}, $bufsize;

print "$count\n";
1
ответ дан 10 December 2019 в 00:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: