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

Обратите внимание: я не ищу «правильный» способ открыть / прочитать файл, или как я должен открывать / читать файл каждый раз. Мне просто интересно узнать, как много людей используют, и, возможно, одновременно изучить несколько новых методов:) *

Очень распространенный блок кода в моих программах Perl открывает файл и читает или записывает его. Я видел так много способов сделать это, и мой стиль выполнения этой задачи несколько раз менялся. Мне просто интересно, какой лучший (если есть лучший способ) способ сделать это?

Я использовал для открытия файла следующим образом:

my $input_file = "/path/to/my/file"; open INPUT_FILE, "<$input_file" || die "Can't open $input_file: $!\n"; 

Но я думаю, что есть проблемы с ловушкой ошибок.

Добавление скобок, похоже, устраняет захват ошибок:

 open (INPUT_FILE, "<$input_file") || die "Can't open $input_file: $!\n"; 

Я знаю, что вы также можете назначить дескриптор файла переменной, поэтому вместо использования «INPUT_FILE», как я сделал выше, я мог бы использовать $ input_filehandle – это лучше?

Для чтения файла, если он мал, что-то не так с globbing, как это?

 my @array = ; 

или

 my $file_contents = join( "\n",  ); 

или если вы всегда проходите цикл, например:

 my @array; while () { push(@array, $_); } 

Я знаю, что в Perl существует так много способов добиться чего-то, мне просто интересно, есть ли предпочтительные / стандартные методы открытия и чтения в файле?

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

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

Причины:

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

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

 my @lines = <$input_fh>; 

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

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

Для длинных файлов вам нужно будет перебирать строки с помощью while или использовать read.

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

 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 по-прежнему не определен здесь, но остальное кошерно.

Когда мне приходится писать «или умереть», везде меня задирают. Мой предпочтительный способ открыть файл выглядит следующим образом:

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

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

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

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

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

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

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

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

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

Что-то, что вы сейчас делаете, вызывает у вас проблемы? Если нет, разве у вас нет проблем решить? 🙂

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

Удачи, 🙂

Это правда, что существует как можно больше способов открыть файл в 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(); 

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

Для 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; 

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

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

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

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

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

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

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

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

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

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

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

 open INPUT_FILE, "<$input_file" or die "Can't open $input_file: $!\n"; 

Дамиан Конвей делает это так:

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

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

  • как читать все файлы внутри определенной папки
  • Является ли HashMap streamобезопасным для разных ключей?
  • C # - Получить список файлов, за исключением скрытых
  • C ++ Обработка файлов: разница между ios: app и ios: ate?
  • Пакетный эквивалент обратных ссылок Баша
  • читать файл назад (последняя строка первая)
  • Лучший способ писать байты в середине файла в Java
  • Удаление файла или папки
  • Java: разделение имени файла на базу и расширение
  • Каков наилучший / самый простой способ чтения в XML-файле в приложении Java?
  • Рекурсивно перечислять файлы в Java
  • Давайте будем гением компьютера.