Ключевые слова:perl, binary, example, (найти похожие документы)
Date: Wed, 6 Mar 2002 08:12:47 +0000 (UTC)
From: Artem Chuprina <ran@ice.ru>
Newsgroups: fido7.ru.cgi.perl
Subject: Работа с бинарными файлами на Perl
# Полагаем, что в $path хранится путь к файлу. Относительный или абсолютный -
# неважно, важно, чтобы по этому пути находился нужный файл
# my-переменные хороши тем, что по выходе из области видимости (по тому же
# die или просто по завершении функции) они дохнут. Для объектов IO::Handle и
# потомков (в данном случае IO::File) это означает автоматическое закрытие
# файла и освобождение соответствующих ресурсов. Однако помимо этого, я
# постарался написать код так, чтобы с глобами он тоже работал
use IO::File;
# Специфика CGI состоит в том, что к одному файлу одновременно могут ломиться
# несколько процессов. Поэтому файлы мы будем лочить. Если у кого DOS-based
# винда, этому несчастному придется это делать иначе. Я бы посоветовал
# радикально - путем смены операционки. Хотя бы на NT-based. Для того, чтобы
# лочить файлы системно-независимо, надо импортировать несколько констант из
# модуля Fcntl.
use Fcntl qw(:flock);
# Чтение
my $fh = new IO::File "< $path" or die "Cannot open $path : $!";
# Требуем блокировку на чтение. flock - функция блокирующая, то есть она будет
# ждать, пока нужный лок не дадут. Она умеет работать в неблокирующем режиме,
# но это отдельная песня
flock($fh,LOCK_SH);
# для текстового файла - чтение по строкам
while (my $line = <$fh>) {
# Тут работаем со строкой, считанной (вместе с \n) в $line
}
# для бинарного файла - чтение по блокам
binmode($fh);
my $buf;
# По поводу этой константы можно развернуть отдельную дискуссию. Читайте
# Стивенса, и ваши волосы будут;
my $buflen = 8192;
# Если Вы уверены, что весь файл влезет в память без особых проблем, то эту
# строчку можно заменить на
my $buflen = (stat($fh))[7];
# Если быть совсем эстетом, то следует использовать File::stat, который
# переопределяет stat так, что в скалярном контексте он возвращает объект, к
# полям которого можно обращаться по имени, в данном случае ->size
while (read($fh,$buf,$buflen)) {
# Тут работаем с блоком, считанным в $buf
}
# Если у нас объект IO::File, то файл можно не закрывать, а просто дождаться,
# когда $fh выйдет за пределы видимости. Если глоб, то файл закрыть
# обязательно. Снимать лок в норме не надо, снимется сам при закрытии
close($fh) or die "Error closing $path : $!";
# Запись
my $fh = new IO::File "> $path" or die "Cannot open $path : $!";
# Требуем блокировку на запись
flock($fh,LOCK_EX);
# Для бинарного файла устанавливаем режим бинарного файла, остальное одинаково
binmode($fh);
...
# Успешность записи надо проверять
print $fh $data or die "Write to $path failed: $!";
...
close($fh) or die "Error closing $path : $!";
--
Artem Chuprina
Communiware.net
RFC2822: <ran@ran.pp.ru>, FIDO: 2:5020/358.49, ICQ: 13038757