Что лучший способ состоит в том, чтобы открыть и считать файл в Perl?

44
задан Peter Mortensen 3 December 2015 в 14:51
поделиться

12 ответов

Нет никаких универсальных стандартов, но существуют причины предпочесть один или другой. Моя предпочтительная форма - это:

open( my $input_fh, "<", $input_file ) || die "Can't open $input_file: $!";

причины:

  • Вы сразу сообщаете об ошибках. (Замена "умирает" с, "предупреждают", если это - то, что Вы хотите.)
  • Ваш дескриптор файла теперь считается на ссылку, поэтому как только Вы не используете его, он будет автоматически закрыт. Если Вы используете глобальное имя INPUT_FILEHANDLE, то необходимо закрыть файл вручную, или это останется открытым до выходов программы.
  • индикатор режима чтения "<"; разделяется от $input_file, увеличивая удобочитаемость.

следующее является большим, если файл является маленьким, и Вы знаете о желании всех строк:

my @lines = <$input_fh>;

можно даже сделать это, если необходимо обработать все строки как единственную строку:

my $text = join('', <$input_fh>);

Для длинных файлов Вы захотите выполнить итерации по строкам с в то время как, или чтение использования.

59
ответ дан rjh 26 November 2019 в 21:44
поделиться

Если Вы хотите весь файл как единственную строку, нет никакой потребности выполнить итерации через него.

use strict;
use warnings;
use Carp;
use English qw( -no_match_vars );
my $data = q{};
{
   local $RS = undef; # This makes it just read the whole thing,
   my $fh;
   croak "Can't open $input_file: $!\n" if not open $fh, '<', $input_file;
   $data = <$fh>;
   croak 'Some Error During Close :/ ' if not close $fh;
}

Вышеупомянутое удовлетворяет perlcritic --brutal, который является хорошим способом протестировать на 'лучшие практики':). $input_file все еще не определено здесь, но остальное является кошерным.

15
ответ дан Peter Mortensen 26 November 2019 в 21:44
поделиться

Необходимость записать 'или умереть' везде сводит меня с ума. Мой предпочтительный способ открыть файл похож на это:

use autodie;

open(my $image_fh, '<', $filename);

, В то время как это очень мало вводит, существует много важных вещей отметить, которые продолжаются:

  • Мы используем эти , автоумирают прагма, что означает, что весь Perl создал-ins, выдаст исключение, если что-то пойдет не так, как надо. Это избавляет от необходимости запись or die ... в Вашем коде, это производит дружественные, человекочитаемые сообщения об ошибках и имеет лексический контекст. Это доступно от CPAN.

  • Мы используем версию с тремя аргументами открытых. Это означает, что, даже если у нас есть забавное имя файла, содержащее символы такой как <, > или |, Perl все еще сделает правильную вещь. В моем безопасность Perl учебное руководство в OSCON я показал много способов стать с 2 аргументами open для неправильного поведения. Примечания для этого учебного руководства доступны для бесплатная загрузка от Обучения Perl Австралия .

  • Мы используем скалярный дескриптор файла. Это означает, что мы не собираемся быть одновременно закрытием чужого дескриптора файла того же имени, которое может произойти, если мы используем дескрипторы файлов пакета. Это также означает strict, может определить опечатки, и что наш дескриптор файла будет очищен автоматически, если это выйдет из объема.

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

  • дескриптор файла заканчивается _fh. Если мы видим, что мы используем его как регулярный скаляр, то мы знаем, что это - вероятно, ошибка.

14
ответ дан Peter Mortensen 26 November 2019 в 21:44
поделиться

Если Ваши файлы являются достаточно маленькими, что чтение всего этого в память выполнимо, используйте File::Slurp . Это читает и пишет, что полные файлы с очень простым API, плюс он делает всю проверку ошибок, таким образом, Вы не имеете к.

11
ответ дан Dave Rolsky 26 November 2019 в 21:44
поделиться

Нет никакого лучшего способа открыть и считать файл. Это - неправильный вопрос спросить. Что находится в файле? В каком количестве данных Вы нуждаетесь в какой-либо точке? Вам нужны все данные сразу? Что необходимо сделать с данными? Необходимо понять тех перед размышлением о том, как необходимо открыть и считать файл.

что-нибудь, что Вы делаете теперь порождение Вас проблемы? В противном случае у разве Вас нет лучших проблем решить?:)

большей частью Вашего вопроса является просто синтаксис, и этому все отвечают в документации Perl (особенно ( perlopentut). Вы также хотели бы брать Изучение Perl, который отвечает на большинство проблем, которые Вы имеете в своем вопросе.

Удача:)

6
ответ дан brian d foy 26 November 2019 в 21:44
поделиться

Это верно, что существует столько же лучших способов открыть файл в Perl, сколько существует

$files_in_the_known_universe * $perl_programmers

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

use strict;
use warnings;

use IO::File;

my $file = shift @ARGV or die "what file?";

my $fh = IO::File->new( $file, '<' ) or die "$file: $!";
my $data = do { local $/; <$fh> };
$fh->close();

# If you didn't just run out of memory, you have:
printf "%d characters (possibly bytes)\n", length($data);

И при движении линию за линией:

my $fh = IO::File->new( $file, '<' ) or die "$file: $!";
while ( my $line = <$fh> ) {
    print "Better than cat: $line";
}
$fh->close();

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

5
ответ дан 26 November 2019 в 21:44
поделиться

Для OO мне нравится:

use FileHandle;
...
my $handle = FileHandle->new( "< $file_to_read" );
croak( "Could not open '$file_to_read'" ) unless $handle;
...
my $line1 = <$handle>;
my $line2 = $handle->getline;
my @lines = $handle->getlines;
$handle->close;
5
ответ дан Axeman 26 November 2019 в 21:44
поделиться

Считайте весь $file файла в переменный $text с одной строкой

$text = do {local(@ARGV, $/) = $file ; <>};

или как функция

$text = load_file($file);
sub load_file {local(@ARGV, $/) = @_; <>}
3
ответ дан 26 November 2019 в 21:44
поделиться

Я когда-то использовал

open (FILEIN, "<", $inputfile) or die "...";
my @FileContents = <FILEIN>;
close FILEIN;

шаблон регулярно. В наше время я использую File::Slurp для маленьких файлов, которые я хочу держать полностью в памяти, и Tie::File для больших файлов, к которым я хочу масштабируемо обратиться и/или файлы, которые я хочу изменить на месте.

4
ответ дан Svante 26 November 2019 в 21:44
поделиться

Если эти программы только для Вашей производительности, безотносительно работ! Сборка в такой обработке ошибок, как Вы думаете, что Вам нужно.

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

Одна подсказка я добрался из одной из глав в Прагматически настроенном Программисте (Hunt & Thomas), то, что Вы могли бы хотеть иметь сценарий, сохраняют резервное копирование файла для Вас, прежде чем это перейдет к разрезанию работы и игре в кости.

2
ответ дан John 26 November 2019 в 21:44
поделиться

|| оператор имеет более высокий приоритет, таким образом, это оценено сначала прежде, чем отправить результат "открыться"... В коде Вы упомянули, используйте "или" оператор вместо этого, и у Вас не было бы той проблемы.

open INPUT_FILE, "<$input_file"
  or die "Can't open $input_file: $!\n";
2
ответ дан Peter Mortensen 26 November 2019 в 21:44
поделиться

Damian Conway делает это этот путь:

$data = readline!open(!((*{!$_},$/)=\$_)) for "filename";

Но я не рекомендую это Вам.

1
ответ дан ysth 26 November 2019 в 21:44
поделиться
Другие вопросы по тегам:

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