В Perl для работы с файлами используется открытие дескрипторов с помощью open. Помимо стандартных дескрипторов (STDIN, STDOUT, STDERR), можно создавать свои и управлять ими.
Перл использует понятие слоёв ввода-вывода (:encoding, :utf8, :raw и др.), чтобы корректно обрабатывать разные типы файлов и кодировок. По умолчанию Perl может работать в текстовом режиме (с переводом строк) или бинарном.
open my $fh, '<:encoding(UTF-8)', 'file.txt' or die $!; while (my $line = <$fh>) { print $line; } close $fh;
open my $fh, '<:raw', 'image.bin' or die $!; read($fh, my $data, -s 'image.bin'); close $fh;
Правильный выбор слоя (:raw для бинарных, :encoding(NAME) для текстовых) обеспечивает корректные чтение и запись.
Если открыть файл с помощью конструкции
open FH, '<', $fileи прочитать бинарные данные, мы всегда получим корректный результат?
Ответ: Нет! Без указания :raw Perl на некоторых платформах будет автоматически преобразовывать символы перевода строки (например, CRLF → LF на Windows). Для чтения бинарных файлов всегда используйте режим :raw:
open my $fh, '<:raw', 'file.bin';
История
В одном корпоративном проекте разработчики работали с текстовыми логами, считая строки без указания кодировки. В результате логи в UTF-8 иногда "ломались" — файл read был повреждён при чтении кириллических символов, т.к. Perl неверно интерпретировал байты. Ошибка была устранена только после явного добавления слоя
:encoding(UTF-8)в вызовеopen.
История
На Windows при копировании бинарных файлов считали данные с помощью
open FH, '<', 'binfile.dat'и записывали без указания режима. Программа "ломала" изображения, т.к. в потоке перевода строк CRLF менялся на LF, что приводило к невалидным бинарным данным. Слой:rawисправил проблему.
История
В внешнем API был требован вывод STDOUT только в UTF-8, а программисты использовали
binmode STDOUT, ':encoding(UTF-8)'проблема ушла.