Ранее в Учебнике Perl мы узнали, как открывать файлы для чтения или записи. К несчастью, поискав в интернете или в корпоративных проектах, зачастую можно увидеть использование немного другого синтаксиса.
Давайте узнаем, почему так делают, в чем там проблема и почему следует этого избегать.
Так что же делать?
Прежде чем рассказывать, как делать не надо, позвольте дать ссылки на статьи, в которых объясняется, как делать надо:
Прочитайте, как открывать файлы современным способом и как в Perl открывать файлы для записи.
Теперь давайте вернемся к старым, и уже-не-таким-хорошим практикам.
Старый, не рекомендуемый к использованию способ
До выхода perl 5.6 - то есть до 2000 года - чтобы открыть файл для записи, мы писали такой код:
open OUT, ">$filename" or die ...;
и так для чтения:
open IN, $filename or die ...;
Часть «or die» с тех пор не изменилась, здесь мы ее целиком не пишем.
Как вы видите, open
принимает два параметра. Первый - это последовательность букв (обычно в
верхнем регистре). Сюда попадет файловая ссылка. Второй - комбинация режима открытия и пути к
открываемому файлу.
На деле, в первом случае мы видим знак «больше», означающий, что мы открываем файл для
записи, но во втором примере мы пропустили режим открытия. Это из-за того, что open()
по
умолчанию использует режим чтения.
Здесь два больших отличия от изученной нами практики:
Глобальная файловая ссылка
Первое состоит в использовании для файловой ссылки странной переменной без $
в начале. (По
сути, это bareword, но он не вызывает ошибки Bareword not
allowed while "strict subs" in use.)
Это по-прежнему работает, как и в прежние времена, но есть некоторые связанные с этим проблемы:
Использованная переменная становится глобальной для всего скрипта, так что если кто-то использует для своей переменной то же имя (в нашем примере это IN или OUT), то она перекроется с вашей.
Кроме того, такие переменные сложнее, чем обычные скаляры, передавать функциям.
open с двумя параметрами
Второе отличие это то, что в этих примерах в open
передается только два параметра.
Что если переменная $filename
, которую мы использовали в открытии файла для чтения,
содержит >/etc/passwd ?
Ой.
Строка open IN, $filename
откроет этот файл для записи.
Мы только что удалили файл с паролями на нашем Linux'е.
Это нехорошо.
Нужно закрывать файловую ссылку
Еще одно преимущество скалярных переменных с ограниченной областью видимости, применяемых для хранения файловых ссылок, состоит в том, что файлы автоматически закрываются, когда переменная покидает область видимости.
Как избегать этих проблем?
Лучше всего избегать использования обеих этих праткик, и использовать «новый» (появившийся в 2000 году!) open с тремя параметрами и скалярную лексическую переменную для открытия файлов и хранения файловой ссылки.
В Perl::Critic даже есть политики, которые помогут вам проанализировать код и найти все места, где кто-то использовал одну из форм, приведенных выше.
Хорошее и Плохое чтение
Плохое:
open IN, $filename or die ...;
Хорошее:
open my $in, '<', $filename or die ...;
Хорошая и Плохая запись
Плохая:
open IN, ">$filename" or die ...;
Хорошая:
open my $in, '>', $filename or die ...;