Листинг 6.10. Чтение записей определенной длины
#! perl -w
open(F1, "in.dat") or die "Ошибка открытия файла: $!";
$str = "1234567890";
read F1, $str, 9; # Чтение девяти байтов в
# переменную $str без смещения
print $str,"\n"; # $str = "********\n"
read F1, $str, 8, length($str);
print $str,"\n"; # $str - "*******\n* PERL *"
В программе из листинга 6.10 функция
length( )
используется для определения количества символов (байтов), содержащихся в скалярной переменной.
После выполнения первой операции чтения содержимое переменной $str было уничтожено, так как эта
функция read ( ) вызывалась без смешения. При втором чтении хранившиеся данные в переменной $str
были полностью сохранены. Обратите внимание, что символ перехода на новую строку, содержащийся в
первой строке файла in.dat, также учитывается при чтении функцией read( ) записей определенной длины.
Следует не забывать об этом обстоятельстве при чтении информации из «многострочного» файла функцией read( ).
Небуферизованный ввод-вывод
Функции чтения из файла sysread( ), записи в файл syswrite( ) и установки указателя текущей позиции
файла sysseek( ) являются аналогами рассмотренных нами функций read( ),print( ) и seek( ), но, в отличие
от последних, они напрямую обращаются к соответствующим функциям операций системы, а не к функциям
стандартной библиотеки ввода-вывода С, минуя тем самым создаваемый этими функциями буфер для выполнения
операций чтения и записи в файл. Заметим, что аналога буферизованной функции tell ( ) не существует,
ее функциональность реализуется функцией sysseek( ).
При вызове функций небуферизованного чтения и записи им передается одинаковый набор параметров,
полностью соответствующий параметрам функции read:
sysread ДЕСКРИПТОР, ПЕРЕМЕННАЯ, ДЛИНА [,СМЕЩЕНИЕ];
syswrite ДЕСКРИПТОР, ПЕРЕМЕННАЯ, ДЛИНА [,СМЕЩЕНИЕ];
Возвращаемым значением этих функций является истинное количество соответственно прочитанных или
записанных в файл байтов, 0 в случае достижения конца файла или undef при возникновении ошибки.
Соответственно набор параметров функции sysseek( ) полностью соответствует передаваемым параметрам
в функцию seek( ):
sysseek ДЕСКРИПТОР, СМЕЩЕНИЕ, ТОЧКА_ОТСЧЕТА;
Все сказанное относительно использования функции seek( ) полностью переносится и на ее
небуферизованный аналог.
Функциональность буферизованной операции tell( ) реализуется следующим вызовом функции sysseek( ):
$position = sysseek Fl, 0, 1; # Текущая позиция указателя файла
Программа демонстрирует использование небуферизованных функций ввода-вывода для обработки
содержимого файла.
#! perl -w
use Fcntl;
# Открытие файла в режиме чтение/запись
sysopen F1, "in.dat", O_RDWR;
# Чтение блока в 14 байтов
$read = sysread F1, $string, 14;
warn "Прочитано $read байтов вместо 14\n" if $read != 14;
# Установка текущей позиции (на 15 байтов)
$position = sysseek Fl, 0, 1;
die "Ошибка позиционирования: $!\n" unless defined $position;
# Запись строки в текущей позиции
$string = "Новое Значение";
$written = syswrite F1, $string, length($string);
die "Ошибка записи: $!\n" if $written != length($string);
# Закрытие файла
close F1 or die $!;
При работе с небуферизованными функциями ввода-вывода следует всегда проверять завершение операции
чтения, записи или позиционирования. Стандартная система ввода-вывода, через которую реализуется
буферизованный ввод-вывод, сама проверяет завершение указанных операций и отвечает за него, если процесс
по каким-то причинам был прерван на середине записи. При небуферизованном вводе-выводе об этом должен
позаботиться программист.