W Perl do pracy z plikami używa się otwierania deskryptorów za pomocą open. Oprócz standardowych deskryptorów (STDIN, STDOUT, STDERR), można tworzyć własne i zarządzać nimi.
Perl używa pojęcia warstw wejścia-wyjścia (:encoding, :utf8, :raw i inne), aby poprawnie przetwarzać różne typy plików i kodowania. Domyślnie Perl może działać w trybie tekstowym (z konwersją linii) lub binarnym.
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;
Poprawny wybór warstwy (:raw dla binarnych, :encoding(NAME) dla tekstowych) zapewnia poprawne czytanie i pisanie.
Czy otwierając plik za pomocą konstrukcji
open FH, '<', $filei odczytując dane binarne, zawsze uzyskamy poprawny wynik?
Odpowiedź: Nie! Bez wskazania :raw Perl na niektórych platformach automatycznie przekształci znaki końca linii (np. CRLF → LF na Windows). Do odczytu plików binarnych zawsze używaj trybu :raw:
open my $fh, '<:raw', 'file.bin';
Historia
W jednym projekcie korporacyjnym programiści pracowali z tekstowymi logami, odczytując linie bez wskazania kodowania. W rezultacie logi w UTF-8 czasami "psuły się" — plik read został uszkodzony podczas odczytu znaków cyrylicy, ponieważ Perl błędnie interpretował bajty. Błąd został naprawiony dopiero po wyraźnym dodaniu warstwy
:encoding(UTF-8)w wywołaniuopen.
Historia
Na Windows podczas kopiowania plików binarnych dane były odczytywane za pomocą
open FH, '<', 'binfile.dat'i zapisywane bez wskazania trybu. Program "psuł" obrazy, ponieważ w strumieniu konwersji końca linii CRLF zmieniało się na LF, co prowadziło do nieprawidłowych danych binarnych. Warstwa:rawnaprawiła problem.
Historia
W zewnętrznym API wymagano wyjścia STDOUT tylko w UTF-8, a programiści używali
binmode STDOUT, ':encoding(UTF-8)'problem zniknął.