Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 [ 69 ] 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103

Если, как в данном случае, файлы/etc/xx.dir и/etc/xx.pag открыть нельзя, то вызов dbmopen возвращает значение "ложь" без попытки создать эти файлы.

DBM-массив остается открытым в течение выполнения всей программы. Когда программа заверщается, разрывается и связь с DBM-базой данных. Эту связь можно разорвать и способом, близким к закрытию дескриптора файла - с помощью функции dbmclose:

dbmclose(%А) ;

Как и функция close, dbmclose возвращает значение "ложь", если что-нибудь происходит не так, как надо.

Использование DBM-xema

После открытия базы данных обращения к DBM-xeuiy преобразуются в обращения к базе данных. Изменение значения в хеше или ввод в него нового значения вызывает немедленную запись соответствующих элементов в файлы на диске. Например, после открытия массива %fred из предьщущего примера мы можем обращаться к элементам базы данных, вводить в нее новые элементы и удалять существующие:

$FRED{"fred"} = "bedrock"; # создать (или обновить) элемент

delete $FRED{"barney"}; # удалить элемент базы данных

foreach $кеу (keys %FRED) { # пройти по всем значениям print "$кеу has value of $FRED{$кеу}\n";

Последний цикл должен просмотреть весь файл на диске дважды: один раз для выборки ключей, а второй - для поиска значений, соответствующих этим ключам. Если вы просматриваете DBM-хеш, то более эффективным способом с точки зрения эксплуатации диска является использование операции each, которая делает всего один проход:

while (($кеу, $value) = each(%FRED)) { print "$кеу has value of $value\n";

Если вы обращаетесь к системным DBM-базам данных, например к базам данных, созданным системами sendmail и NIS, вы должны иметь в виду, что в плохо написанных С-программах в конце строк иногда стоит символ NUL (\0). Программам библиотеки DBM этот NUL не нужен (они обрабатывают двоичные данные с помощью счетчика байтов, а не строки с символом NUL на конце), поэтому он хранится как часть данных. В таком случае вы должны добавлять символ NUL в конец своих ключей и отбрасывать NUL, стоящий в конце возвращаемых значений, иначе данные не будут иметь смысла.



Например, чтобы найти имя merlyn в базе данных псевдонимов, можно сделать так:

dbmopen(%ALI, "/etc/aliases", undef) die "no aliases?";

$value = $ALI("raerlyn\0"}; # обратите внимание на добавленный NOL

chop($value); # удалить добавленный NUL

print "Randals mail is headed for: $value\n"; # показать результат

В вашей версии UNIX база данных псевдонимов может храниться не в каталоге /etc, а в каталоге/«5 . Чтобы выяснить, где именно она хранится, придется провести маленькое расследование. Новые версии sendmail этим NUL-дефектом не страдают.

Базы данных произвольного доступа с записями фиксированной длины

Еще одна форма хранения данных - файл на диске, предназначенный для записей фиксированной длины. В этой схеме данные состоят из ряда записей одинаковой длины. Нумерация этих записей либо не имеет значения, либо определяется по какой-нибудь схеме индексации.

Например, у нас может быть ряд записей со следующими данными: 40 символов - имя, один символ - инициал, 40 символов - фамилия и двухбайтовое целое - возраст. Таким образом, длина каждой записи составляет 83 байта. Если бы мы читали все эти данные в базе данных, то делали бы это порциями по 83 байта до тех пор, пока не добрались до конца. Если бы мы хотели перейти к пятой записи, то мы пропустили бы четыре раза по 83 байта (332 байта) и прочитали бы непосредственно пятую запись.

Perl поддерживает программы, которые используют файл с подобными записями. Помимо того, что вы уже знаете, понадобятся еще несколько операций:

1. Открытие файла на диске для чтения и записи.

2. Переход в этом файле на произвольную позицию.

3. Выборка данных фиксированной длины, а не до следующего символа новой строки.

4. Запись данных блоками фиксированной длины.

В функции open перед спецификацией, задающей способ открытия файла (для чтения или записи), необходимо записать знак плюс, указав таким образом, что данный файл в действительности открывается и для чтения, и для записи. Например:

open (А, "+<Ь"); # открыть файл Ь для чтения-записи (ошибка, если файл отсутствует)

open(С, "+>d"); # создать файл d с доступом для чтения-записи

ореп(Е, "+>>f"); # открыть или создать файл f с доступом для чтения-записи



Отметим, что все, что мы сделали - это добавили знак плюс к спецификации, задающей направление ввода-вывода данных в файл.

Открыв файл, мы должны перейти на определенную позицию в нем. Это делается с помощью функции seek, которая принимает те же три параметра, что и библиотечная программа fseek(3). Первый параметр - это дескриптор файла, а второй параметр задает смещение, которое интерпретируется в совокупности с третьим параметром, Как правило, в качестве третьего параметра ставится нуль, чтобы второй параметр задавал абсолютную позицию для следующего чтения из файла или записи в файл. Например, чтобы перейти к пятой записи в дескрипторе файла names (как описано выше), можно сделать так:

seek(NAMES,4*83,0);

После перемещения указателя в файле на нужную позицию следующая операция ввода или вывода будет начинаться с этой позиции. Для вывода используйте функцию print, но не забудьте, что записываемые данные должны иметь строго определенную длину. Чтобы сформировать запись правильной длины, можно воспользоваться функцией раек:

print NAMES раск("А40 А А40 s", $first, $raiddle, $last, $age);

В данном случае pack задает 40 символов для $first, один символ - для $middle, еще 40 символов - для $last и короткое целое (два байта) для $аде. Определенная таким образом запись будет иметь в длину 83 байта и начинаться с текущей позиции в файле.

Наконец, нам нужно узнать, как выбрать конкретную запись. Конструкция <names> возвращает все данные, начиная с текущей позиции и до следующего символа новой строки, однако в нашем случае предполагается, что данные занимают 83 байта и, вероятно, символ новой строки непосредственно в записи отсутствует. Поэтому вместо нее мы используем функцию read, которая по внешнему виду и принципу работы очень похожа на свою UNIX-коллегу:

$count = read(NAMES, $buf, 83);

Первый параметр функции read - дескритггор файла. Второй параметр - это скалярная переменная, в которую будут затшсаны прочитанные данные. Третий параметр задает количество байтов, которые нужно прочитать. Возвращает функция read количество фактически прочитанных байтов; как правило, оно равно затребованному количеству байтов, если только дескриптор файла открыт и если вы не находитесь слишком близко к концу файла.

Получив эти 83-символьные данные, разбейте их на компоненты с помощью функции unpack:

($first, $middle, $last, $age) = unpack("A40 A A40 s", $buf);



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 [ 69 ] 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103