Ключевые слова:dbf, perl, win, database, (найти похожие документы)
From: Alexandr N. <novo at sampo.ru>
Newsgroups: email
Date: Mon, 23 Jun 2004 14:31:37 +0000 (UTC)
Subject: Работа с DBF файлами в Perl
Оригинал: http://sk.karelia.ru/dbf/
Установка ActivePerl 5.8.2 и модуля DBD-Xbase для Windows для чтения и
записи dbf-файлов. Шаг за шагом.
Версия 0.0.1.310104-310104.
Шаг 1.
Скачать и установить Windows Installer 2.0+ (если он у вас еще
не установлен) для 9x/Me:
http://downloads.activestate.com/contrib/Microsoft/MSI2.0/9x/InstMsiA.exe
или для NT:
http://downloads.activestate.com/contrib/Microsoft/MSI2.0/NT/InstMsiW.exe
Шаг 2.
Скачать и устанавить Perl для Windows отсюда:
http://activestate.com/Products/Download/Download.plex?id=ActivePerl
Я брал этот (5.8.2):
http://downloads.activestate.com/ActivePerl/Windows/5.8/ActivePerl-5.8.2.808-MSWin32-x86.msi
Шаг 3.
Идем на страничку с модулями:
http://ppm.activestate.com/PPMPackages/zips/8xx-builds-only/Windows/
Качаем модуль DBD-XBase-0.240.zip для чтения/записи в *.dbf файлы.
http://ppm.activestate.com/PPMPackages/zips/8xx-builds-only/Windows/DBD-XBase-0.240.zip
Шаг 4.
Устанавливаем модуль DBD-XBase-0.240.zip:
Разархивируем его в директорию c:\xbase\;
запускаем, например в FAR'e PPM с помощью команды
ppm [enter]
(если не запускается, то после установки Perl надо перезагрузиться);
затем
rep[enter];
help rep[enter]; - читаем help кому интересно
rep add lo c:\xbase\; - место куда мы распаковали Xbase-DBD;
rep off 1; - выключаем остальные репозитории
rep off 1; - выключаем остальные репозитории
если все сделали правильно команда rep должна показать только
репозиторий lo остальные репозитории не активны
quit[enter] - выходим из PPM
переходим в директорию c:\xbase\
говорим
ppm install DBD-XBase.ppd[enter] или ppm install DBD-XBase[enter] (что-то должно сработать :)
Модуль должен установиться.
Шаг 5.
Читаем man'ы :)
Man-страница на сайте автора модуля DBD-Xbase:
http://www.fi.muni.cz/~adelton/perl/man3/XBase.html
Русский перевод этой man-странички (перевел как мог - сильно не пинать :)
http://sk.karelia.ru/dbf/rman.html (прим. копия в конце данной статьи)
Шаг 6.
Пишем программы на Perl, которые позволяют редактировать *.dbf файлы.
Примеры программ:
Программа 1: Этот код обновляет значение поля MSG в тех записях где ID
равно 123;
-----------------
use XBase;
my $table = new XBase "test.dbf" or die XBase->errstr;
for (0 .. $table->last_record) {
my ($deleted, $id) = $table->get_record($_, "ID")
die $table->errstr unless defined $deleted;
next if $deleted;
$table->update_record_hash($_, "MSG" => "New message") if $id == 123;
}
-----------------
Программа 2. Содержимое файла table.dbf копируется в файл str.txt;
в виде:
1|2|3|
1|2|3|
где "|" - разделитель между полями
а каждая следующая выводится запись на новой строке
-----------------
use XBase;
my $table = new XBase "table" or die XBase->errstr;
open (STDOUT,">str.txt");
$table->dump_records("fs" => "|", "rs" => "\n");
close(STDOUT);
$table->close;
-----------------
Программа 3. Создаем на диске файл copy.dbf с нужной структурой
-----------------
use XBase;
my $newtable = XBase->create("name" => "copy.dbf",
"field_names" => [ "ID", "MSG" ],
"field_types" => [ "N", "C" ],
"field_lengths" => [ 6, 40 ],
"field_decimals" => [ 0, undef ]);
-----------------
Шаг 7.
Превращаем cat.pl в cat.bat c помощью команды pl2bat cat.pl;
Получаем обычный *.bat файл, который можно запускать даже из Norton Commander;
В FAR'е или NC жмем F2; INSERT; прописываем нужный *.bat'ник
и теперь по f2 очень легко запустить нужную Perl'овую прогу :)
Enjoy!
Замечания приветствуются.
Шлем на novo@sampo.ru.
CU Alexandr N.
Перевод man XBase
НАЗВАНИЕ
XBase - Perl модуль для чтения и записи dbf файлов
______________________________________________________________________
СИНТАКСИС
use XBase;
my $table = new XBase "dbase.dbf" or die XBase->errstr;
for (0 .. $table->last_record) {
my ($deleted, $id, $msg)
= $table->get_record($_, "ID", "MSG");
print "$id:\t$msg\n" unless $deleted;
}
______________________________________________________________________
ОПИСАНИЕ
Этот модуль может читать и писать Xbase файлы баз данных, известные
как dbf в мире dBase и FoxPro. Можно также читать мемо поля из dbt и
fpt файлов. В альфа версии модуля чтение индексов поддерживается в
тестовом режиме для ndx, ntx, mdx, idx и cdx - смотри DBD::Index(3)
man.
Методы, которые поддерживает модуль Xbase:
Основные методы
new
Создает Xbase объект, загружает информацию о таблице dbf файла. Первым
параметром должно быть имя существующего dbf файла (таблицы
фактически) для чтения. Суфикс .dbf будет добавлен, если необходимо.
Этот метод создает и инициализирует новый объект, также проверит мемо
файл, если нужно.
Параметры могут быть также указаны в форме хэша: значение name есть
имя таблицы, следующие поддерживаемые флаги указаны ниже:
memofile определяет не стандартное имя для ассоциированного memo
файла. По умолчанию, это имя dbf файла с расширением dbt или fpt.
ignorememo игнорирует memo файл вообще. Это полезно, если вы потеряли
dbt файл и он вам не нужен. По умолчанию - отключено.
memosep - разделитель memo записей в dBase III dbt файлах. По
стандартам это должен быть "\x1a\x1a". Предполагается, что
разделителем может также быть "\x1a". XBase.pm пытается определить
какой разделитель в вашем dbt, но если он
не может это сделать, то вы должны указать какой разделитель
используется сами.
nolongchars предотвращает от того, чтобы Xbase рассматривал десятичное
значение полей типа character как максимальный байт длинны - есть
несколько <<кривых>> продуктов производящих поля типа character с
установленным десятичным значением.
my $table = new XBase "table.dbf" or die XBase->errstr;
my $table = new XBase "name" => "table.dbf", "ignorememo" => 1;
recompute_lastrecno заставляет XBase.pm не верить информации о числе
записей в заголовке dbf файла и пересчитать число записей. Используйте
этот параметр только если вы знаете, что какое-то другое программное
обеспечение может создать неправильный заголовок файла.
close
Закрывает объект/файл. Без аргументов.
create
Создает новый файл базы данных на диске и инициализирует в нем 0
записей. Также будут созданы Dbt (memo) файлы, если таблица содержит
memo поля.
Вы можете вызывать этот метод как метод другого XBase объекта и тогда
вы должны передать name значения хэша; структура (поля) нового файла
будут такими же как и у оригинального объекта.
If you call create using class name (XBase), you have to (besides
name) also specify another four values, each being a reference to
list: field_names, field_types, field_lengths and field_decimals. The
field types are specified by one letter strings (C, N, L, D, ...). If
you set some value as undefined, create will make it into some
reasonable default.
my $newtable = $table->create("name" => "copy.dbf");
my $newtable = XBase->create("name" => "copy.dbf",
"field_names" => [ "ID", "MSG" ],
"field_types" => [ "N", "C" ],
"field_lengths" => [ 6, 40 ],
"field_decimals" => [ 0, undef ]);
Другие атрибуты: memofile для не стандартного расположения мемо-файла;
codepage - устанавливает флаг кодовой страницы в заголовке dbf файла
(это не будет работать когда XBase.pm читает или пишет данные, хотя
FoxPro будет работать); version - предотвращает различия между dbt
файлов. По умолчанию это версия объекта из которого был создан новый
объект или 3, если вы вызвали этот метод как класс метода
(XBase->create).
Создаваемый файл не должен уже существовать - Xbase не сможет
перезаписать существующий файл. Используйте drop (или unlink) для
удаления существующего файла.
drop
Этот метод закрывает таблицу и удаляет ее с диска (включая связанные
мемо файлы, если они есть)
last_record
Возвращает номер последней записи в файле. Удаленные, но находящиеся в
файле записи тоже считаются.
last_field
Возвращает номер последнего поля в файле, число полей минус 1.
field_names, field_types, field_lengths, field_decimals
Возвращает список полей, типы полей, длину поля, размер десятичных
знаков.
field_type, field_length, field_decimal
По имени поля, возвращает соответствующие переменные. Возвращает
undef, если поле не существует в таблице.
Чтение данных по очереди (одна запись за другой)
Когда вы читатете или записываете записи одну за другой (используя
следующие 6 методов), вы должны первым параметром указать номер записи
в файле. Диапазон всех записей в файле: 0 .. $table->last_record .
get_record
Возвращает список данных (значения полей) для указанной записи в
таблице. Первый указываемый параметр - номер записи в файле.
Если вы не указали любые другие параметры, все значения всех полей
будут возвращены в том порядке в котором они указаны в файле.
Вы можете также указать список полей после номера записи и тогда
только значения этих полей будут возвращены. Первое значение из
возвращаемого листа всегда значение 1/0 _DELETED, которое говорит о
том удалена запись или нет. Таким образом в случае успеха get_record
никогда не возвращает пустой список.
get_record_nf
Вместо имен полей, вы можете указать список номеров полей для чтения.
get_record_as_hash
Возвращает хэш (в списковом контексте) или ссылку на хэш (в скалярном
контексте) содержащий значения полей индексированных по имени полей.
Имя флага удаления - _DELETED; Параметром служит только номер записи;
Имена полей возвращаются в верхнем регистре.
Запись данных
Все три метода записи всегда не удаляют запись. В случае успеха они
возвращают истину - номер записанной записи.
set_record
Параметры: номер записи и список значений полей. Записывает запись в
файл. Не определенные поля (если вы не определяете значения каких-то
полей) будут определены как undef/пустые.
set_record_hash
Задает номер записи и хэша как параметров, задает поля, не определяя
неопределенные/пустые.
update_record_hash
Такой же как set_record_hash, но поля, значения которых не заданы в
хэше сохраняют их значения.
Чтобы пометить запись для удаления или отменить пометку об удаление
используйте методы delete_record и undelete_record,
указав в качестве параметра номер записи.
Различные примеры чтения и записи:
my @data = $table->get_record(3, "jezek", "krtek");
my $hashref = $table->get_record_as_hash(38);
$table->set_record_hash(8, "jezek" => "jezecek", "krtek" => 5);
$table->undelete_record(4);
Этот код обновляет значение поля MSG в тех записях где ID равно 123;
use XBase;
my $table = new XBase "test.dbf" or die XBase->errstr;
for (0 .. $table->last_record) {
my ($deleted, $id) = $table->get_record($_, "ID")
die $table->errstr unless defined $deleted;
next if $deleted;
$table->update_record_hash($_, "MSG" => "New message") if $id == 123;
}
Последовательное чтение файла
Если вы планируете последовательно пройтись по файлу, вы можете
вначале создать курсор и затем повторно вызывать метод fetch, чтобы
получить следующую запись.
prepare_select
Параметрами может быть список возвращаемых имен полей, если параметры
не указаны fetch вернёт значения всех полей.
prepare_select_with_index
Первый параметр - имя файла индексного файла, остальные как выше. Для
типов индексов, которые могут иметь различную индексную структуру в
файле, используйте ссылку на массив вместо имени файла и в этот массив
включите имя файла и имя тэга, и пожеланию тип индекса. Метод fetch
вернет записи в возрастающем порядке согласно индексу.
Следующие методы - методы курсора, а не таблицы.
fetch
Возвращает поля следующей "неудаленной" записи. Список не содержит
флаг _DELETED, это гарантирует что запись не удалена.
fetch_hashref
Возвращает хэш ссылки полей для следующей не удаленной записи.
last_fetched
Возвращает число записей выбранных в последний раз.
find_eq
Этот метод работает только с курсором созданным с помощью
prepare_select_with_index. Курсор будет перемещаться к первой записи
эквивалентной указанному аргументу, или к первой большей записи, если
нет эквивалентной. Следующие выборки тогда проходят нормально.
Примеры использования курсоров:
my $table = new XBase "names.dbf" or die XBase->errstr;
my $cursor = $table->prepare_select("ID", "NAME", "STREET");
while (my @data = $cursor->fetch) {
### do something here, like print "@data\n";
}
my $table = new XBase "employ.dbf";
my $cur = $table->prepare_select_with_index("empid.ndx");
## my $cur = $table->prepare_select_with_index(
["empid.cdx", "ADDRES", "char"], "id", "address");
$cur->find_eq(1097);
while (my $hashref = $cur->fetch_hashref
and $hashref->{"ID"} == 1097) {
### do something here with $hashref
}
Второй пример показывает, что после того как отработал метод find_eq,
метод fetch продолжает работать до конца индекса, так вы должны
проверить находитесь ли вы на записи в заданным значением. И если
здесь нет записи со значением 1097 в индексированном поле, вы только
получите следующую запись по порядку.
Пример с обновлением данных может быть переписан так:
use XBase;
my $table = new XBase "test.dbf" or die XBase->errstr;
my $cursor = $table->prepare_select("ID")
while (my ($id) = $cursor->fetch) {
$table->update_record_hash($cursor->last_fetched, "MSG" => "New message") if $id == 123
}
Сброс содержимого файла на диск
Метод get_all_records возвращает ссылку на массив содержащий массив
значений для каждой не удаленной записи. Параметрами можно указать
список полей возвращаемых для каждой записи.
Для печати содержимого файла в читаемой форме, используйте метод
dump_records. Он печатает все не удаленные записи из файла. По
умолчанию все поля печатаются, разделенные колонками по одной записи в
строке. Этот метод может использовать параметры в форме хэша со
следующими ключами:
rs
Разделитель записей (строк), по умолчанию символ новой строки.
fs
Разделитель полей записи, по умолчанию `|'.
fields
Определяет список полей для печати. По умолчанию undef, т.е. все поля.
undef
Что печатать если поле не определено (значение NULL), по умолчанию
пустая строка.
Пример использования:
use XBase;
my $table = new XBase "table" or die XBase->errstr;
$table->dump_records("fs" => " | ", "rs" => " <-+\n", "fields" => [ "id", "msg" ]);'
Также помните, что здесь есть скрипт dbfdump(1), который печатает.
Ошибки и отладка
Если метод терпит неудачу (возвращает значение <<ложь>> или нулевой
список), ошибку можно узнать с помощью метода errstr. Если new или
create терпят неудачу, и у вас еще нет никаких объектов, вы можете
получить сообщение об ошибке используя XBase->errstr().
Метод header_info возвращает (не печатает) строку с информацией о
файле и о полях.
Модуль XBase::Base(3) определяет некоторые базовые функции которые
унаследованы XBase и XBase::Memo(3) модулями.
______________________________________________________________________
ТИПЫ ДАННЫХ
Символьные поля возвращаются <<как есть>>. Нет символьных таблиц или
других трансляций. Числа конвертируются в Perl'овые числа. Поле типа
data возвращается как 8-ми символьная строка типа 'YYYYMMDD' и когда
вы вставляете даты, вы должны делать это в этой же форме. Проверки на
правильность даты не проводятся. Поле datetime возвращается, как число
секунд (иногда отрицательное) с 1 января 1970 года, возможно с
десятичной частью (с точностью до 1/1000 секунды). Чтобы получить
значение поля используйте gmtime или подобные функции Perl.
Если есть мемо поля в dbf файле, модуль пытается открыть файл с таким
же именем, но с расширением dbt, fpt или smt. Для этого используется
модуль XBase::Memo(3). Модуль читает и пишет эти мемо поля незаметно
(вы даже не знаете об этом) и возвращает данные как скаляр.
______________________________________________________________________
ИНДЕКС, БЛОКИРОВКИ
Новое: Поддержка для ndx, ntx, mdx, idx и cdx индексных форматов
возможно с альфа-статусом тестирования. Поддержка формата ndx уже
более менее стабильна. Пожалуйста читайте XBase::Index(3) man-страницу
и eg/use_index файл в дистрибутиве с примерами и идеями использования.
Пошлите мне примеры ваших файлов данных и предложений для интерфейса,
если Вы нуждаетесь в индексах.
Основные блокирующие методы: locksh, lockex и unlock для общей
блокировки, эксклюзивной блокировки и разблокировки. Они вызывают
flock, но вы должны переопределить их в пакете XBase::Base.
______________________________________________________________________
ССЫЛКИ
Этот модуль был создан благодаря статье "XBase File Format
Description" Erik Bachmann, URL: http://www.e-bachmann.dk/docs/xbase.htm
Спасибо.
______________________________________________________________________
ВЕРСИЯ
0.241
______________________________________________________________________
АВТОР
(c) 1997--2003 Jan Pazdziora, adelton@fi.muni.cz,
http://www.fi.muni.cz/~adelton/ факультет Информатики, Masaryk
University в Brno, Чешская Республика.
All rights reserved. This package is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.
______________________________________________________________________
БЛАГОДАРНОСТИ
Многие люди предоставляли информацию, тестовые файлы, тестовые
результаты и патчи. Этот проект был успешен благодаря им.
Смотрите Changes file с (я надеюсь) полным списком этих людей. Спасибо
вам всем ребята!
Отдельное спасибо Erik Bachmann и его превосходной страничке о
структуре файлов, Frans van Loon, William McKee, Randy Kobes и Dan
Albertsson за долговременное сотрудничество и большое количество
электронных писем, которыми мы обменивались в процессе отладки и
шлифовки поведения модулей; и также еще раз спасибо Dan Albertsson за
предоставленную поддержку моего проекта.
______________________________________________________________________
СМ. ТАКЖЕ
perl(1); XBase::FAQ(3); DBD::XBase(3) и DBI(3) для DBI интерфейса; dbfdump(1);