Perl Language
Файловый ввод-вывод (чтение и запись файлов)
Поиск…
параметры
Режим | Explaination |
---|---|
> | Напишите (trunc) . Перезапишет существующие файлы. Создает новый файл, если файл не найден |
>> | Напишите (добавьте) . Не перезаписывайте файлы, а добавьте новый контент в конце. Будет также создан файл, если он используется для открытия не существующего файла. |
< | Прочитайте . Открывает файл в режиме только для чтения. |
+< | Чтение / запись . Не будет создавать или обрезать файл. |
+> | Чтение / запись (trunc) . Будет создавать и усекать файл. |
+>> | Чтение / запись (добавление) . Будет создавать, но не обрезать файл. |
замечания
chomp
часто используется при чтении из файла. По умолчанию он обрезает символ новой строки, хотя его полная функциональность относится к perldocs .
Остерегайтесь разницы между символами и байтами: не все кодировки, особенно UTF-8, используют 1-байтовые символы. Несмотря на то, что PerlIO обрабатывается почти безупречно, есть одна потенциальная ошибка:
-
read
использует символы для параметров длины и смещения -
seek
иtell
всегда использовать байты для позиционирования
Поэтому не используйте арифметику на основе этих смешанных значений. Вместо этого используйте, например, Encode::encode('utf8',$value_by_read)
чтобы получить октеты (байты) из результата read
, счет которых вы можете использовать с tell
и seek
.
Чтение из файла
my $filename = '/path/to/file';
open my $fh, '<', $filename or die "Failed to open file: $filename";
# You can then either read the file one line at a time...
while(chomp(my $line = <$fh>)) {
print $line . "\n";
}
# ...or read whole file into an array in one go
chomp(my @fileArray = <$fh>);
Если вы знаете, что ваш входной файл UTF-8, вы можете указать кодировку:
open my $fh, '<:encoding(utf8)', $filename or die "Failed to open file: $filename";
После завершения чтения из файла дескриптор файла должен быть закрыт:
close $fh or warn "close failed: $!";
См. Также: Чтение файла в переменную
Другим и более быстрым способом чтения файла является использование модуля File :: Slurper. Это полезно, если вы работаете со многими файлами.
use File::Slurper;
my $file = read_text("path/to/file"); # utf8 without CRLF transforms by default
print $file; #Contains the file body
См. Также: [Чтение файла с помощью slurp]
Запись в файл
Этот код открывает файл для записи. Возвращает ошибку, если файл не может быть открыт. Также закрывает файл в конце.
#!/usr/bin/perl
use strict;
use warnings;
use open qw( :encoding(UTF-8) :std ); # Make UTF-8 default encoding
# Open "output.txt" for writing (">") and from now on, refer to it as the variable $fh.
open(my $fh, ">", "output.txt")
# In case the action failed, print error message and quit.
or die "Can't open > output.txt: $!";
Теперь у нас есть открытый файл, готовый для записи, к которому мы обращаемся через $fh
(эта переменная называется дескриптором файла ). Затем мы можем направлять вывод в этот файл с помощью оператора print
:
# Print "Hello" to $fh ("output.txt").
print $fh "Hello";
# Don't forget to close the file once we're done!
close $fh or warn "Close failed: $!";
Оператор open
имеет в качестве первого параметра скалярную переменную ( $fh
в этом случае). Поскольку он определен в операторе open
он рассматривается как дескриптор файла . Второй параметр ">"
(больше) определяет, что файл открыт для записи. Последний параметр - это путь к файлу для записи данных.
Чтобы записать данные в файл, используется оператор print
вместе с дескриптором файла . Обратите внимание, что в операторе print
нет запятой между дескриптором файла и самим заявлением, просто пробелы.
Открытие файла FileHandle для чтения
Открытие общих текстовых файлов ASCII
open my $filehandle, '<', $name_of_file or die "Can't open $name_of_file, $!";
Это основная идиома для «default» File IO и делает $filehandle
доступным для чтения входным потоком bytes
, отфильтрованный стандартным системным декодером, который может быть локально установлен с open
прагмой
Сам Perl не обрабатывает ошибки при открытии файла, поэтому вы должны сами обрабатывать их, проверяя условие выхода open
. $!
заполняется сообщением об ошибке, которое вызвало отказ.
В Windows декодер по умолчанию является фильтром «CRLF», который отображает последовательности «\ r \ n» на входе в «\ n»,
Открытие двоичных файлов
open my $filehandle, '<:raw', 'path/to/file' or die "Can't open $name_of_file, $!";
Это указывает, что Perl не должен выполнять трансляцию CRLF
в Windows.
Открытие текстовых файлов UTF8
open my $filehandle, '<:raw:encoding(utf-8)', 'path/to/file'
or die "Can't open $name_of_file, $!";
Это указывает, что Perl должен избегать CRLF
перевода, а затем декодировать полученные байты в строки символов (внутренне реализуемые как массивы целых чисел, которые могут превышать 255) вместо строк байтов
Чтение и запись в файл
Прежде чем читать и писать текстовые файлы, вы должны знать, какую кодировку использовать. См. Документацию Perl Unicode для более подробной информации о кодировании . Здесь мы показываем настройку UTF-8 как кодировку и декодирование по умолчанию для open
функции. Это делается с использованием open
прагмы в верхней части вашего кода (сразу после use strict;
режима и use warnings;
было бы уместно):
use strict;
use warnings;
use open qw( :encoding(UTF-8) :std );
Функция open
создает дескриптор файла, который используется для чтения и / или записи в файл. open
функция имеет подпись
open(FILEHANDLE, MODE, FILEPATH)
и возвращает ложное значение, если операция open(FILEHANDLE, MODE, FILEPATH)
с ошибкой. Затем описание ошибки сохраняется в $!
,
чтение
#!/usr/bin/perl
use strict;
use warnings;
use open qw( :encoding(UTF-8) :std ); # Make UTF-8 default encoding
my $file_path = "/path/to/file";
open(my $file_handle, '<', $file_path) or die "Could not open file! $!";
while(my $row = <$file_handle>) {
print chomp($row), "\n";
}
close $file_handle
or warn "Close failed!";
Пишу
#!/usr/bin/perl
use strict;
use warnings;
use open qw( :encoding(UTF-8) :std ); # Make UTF-8 default encoding
my $file_path = "/path/to/file";
open(my $file_handle, '>', $file_path) or die "Could not open file! $!";
print $file_handle "Writing to a file";
close $file_handle
or warn "Close failed!";
Чтение кусков
Открытие и чтение больших файлов может занять некоторое время и ресурсы. Если требуется только небольшая часть содержимого, может быть хорошей идеей прочитать содержимое в кусках, используя функцию read
которая имеет подпись
read(FILEHANDLE, SCALAR, LENGTH, OFFSET)
FILEHANDLE
должен быть открытым дескриптором файла, SCALAR
будет удерживать прочитанные данные после операции. LENGTH
определяет количество символов для чтения, начиная с OFFSET
. Функция возвращает количество прочитанных символов, 0
если конец файла был достигнут, а undef
в случае ошибки.
read($file_handle, $data, 16, 0);
Считывает 16 символов из начала файла в $data
.
«использовать autodie», и вам не нужно будет проверять ошибки открытия / закрытия файла
autodie
позволяет работать с файлами без явной проверки ошибок при открытии / закрытии.
Начиная с Perl 5.10.1, прагма autodie
была доступна в ядре Perl. При использовании Perl автоматически проверяет наличие ошибок при открытии и закрытии файлов.
Ниже приведен пример, в котором все строки одного файла считываются, а затем записываются в конец файла журнала.
use 5.010; # 5.010 and later enable "say", which prints arguments, then a newline
use strict; # require declaring variables (avoid silent errors due to typos)
use warnings; # enable helpful syntax-related warnings
use open qw( :encoding(UTF-8) :std ); # Make UTF-8 default encoding
use autodie; # Automatically handle errors in opening and closing files
open(my $fh_in, '<', "input.txt"); # check for failure is automatic
# open a file for appending (i.e. using ">>")
open( my $fh_log, '>>', "output.log"); # check for failure is automatic
while (my $line = readline $fh_in) # also works: while (my $line = <$fh_in>)
{
# remove newline
chomp $line;
# write to log file
say $fh_log $line or die "failed to print '$line'"; # autodie doesn't check print
}
# Close the file handles (check for failure is automatic)
close $fh_in;
close $fh_log;
Кстати, вы должны технически всегда проверять утверждения print
. Многие люди этого не делают, но perl
(интерпретатор Perl) не делает этого автоматически, и не делает autodie
.
Перемотайте файл-дескриптор
Иногда бывает необходимо отступить после прочтения.
# identify current position in file, in case the first line isn't a comment
my $current_pos = tell;
while (my $line = readline $fh)
{
if ($line =~ /$START_OF_COMMENT_LINE/)
{
push @names, get_name_from_comment($line);
}
else {
last; # break out of the while loop
}
$current_pos = tell; # keep track of current position, in case we need to rewind the next line read
}
# Step back a line so that it can be processed later as the first data line
seek $fh, $current_pos, 0;
Чтение и запись сжатых файлов gzip
Запись gzip-файла
Чтобы написать gzip-файл, use
модуль IO::Compress::Gzip
и создайте дескриптор файла, создав новый экземпляр IO::Compress::Gzip
для желаемого выходного файла:
use strict;
use warnings;
use open qw( :encoding(UTF-8) :std ); # Make UTF-8 default encoding
use IO::Compress::Gzip;
my $fh_out = IO::Compress::Gzip->new("hello.txt.gz");
print $fh_out "Hello World!\n";
close $fh_out;
use IO::Compress::Gzip;
Чтение из gzip-файла
Чтобы прочитать из gzip-файла, use
модуль IO::Uncompress::Gunzip
а затем создайте дескриптор файла, создав новый экземпляр IO::Uncompress::Gunzip
для входного файла:
#!/bin/env perl
use strict;
use warnings;
use open qw( :encoding(UTF-8) :std ); # Make UTF-8 default encoding
use IO::Uncompress::Gunzip;
my $fh_in = IO::Uncompress::Gunzip->new("hello.txt.gz");
my $line = readline $fh_in;
print $line;
Установка кодировки по умолчанию для ввода-вывода
# encode/decode UTF-8 for files and standard input/output
use open qw( :encoding(UTF-8) :std );
Эта pragma
изменяет режим чтения и записи текста (файлы, стандартный ввод, стандартный вывод и стандартную ошибку) по умолчанию в UTF-8, что обычно требуется при написании новых приложений.
ASCII - это подмножество UTF-8, поэтому это не вызовет проблем с устаревшими файлами ASCII и поможет защитить вас от случайного повреждения файлов, которое может произойти при обработке файлов UTF-8 как ASCII.
Тем не менее, важно знать, что такое кодирование ваших файлов, с которыми вы имеете дело, и обрабатывать их соответственно. ( Причины того, что мы не должны игнорировать Unicode. ) Для более глубокого изучения Unicode обратитесь к теме Unicode Perl .