©Vadikoff - Блог - Читаем файлы формата dBase 4 : 2007-2019, Vadikoff.RU, Ltd. mail: mail@vadikoff.ru, tel.: +7 (915) 636-42-33, ICQ UIN: 910-499, Skype: vadikoff.ru

CMS Version: 1.0.10 (mod: Blog)
Вход
Регистрация
Господь создал всех людей добрыми и счастливыми по умолчанию. И всё было бы хорошо, если бы они не начали ковыряться в настройках.
Неизвестный
Читаем файлы формата dBase 4
Читаем файлы формата dBase 4
Тематика: PHP
Дата публикации: 16 января 2016

Когда-то у мне предстояла задача написать сайт работающий с 1С предприятием(файловой версии), конечно на MSSQL это было бы куда удобнее, и нужно было переносить номенклатуру на сайт. Таким образом предстояло разобраться с форматом файлов dBase 4, именно этот формат использует 1С 7.7 - прошлый век, конечно, но деваться было некуда и пришлось написать класс для работы с таким форматом :)

В этой статья я представлю часть класс способного считывать записи из файлов формата dBase 4, возможно это кому-нибудь пригодится.

//Для начала создадим сам класс и назовём его dBase;
class dbase {
  var $dbf;
  var $info = array();
  var $fields = array();
  var $row_record_flag = 0;

//Эта функция нам понадобиться для преобразования байтов из файла в переменную integer(числовую)
function _str2long( $_string ) {
    for ($x = 0; $x <= strlen($_string); $x++) {
        $_return += (ord($_string[$x]) * pow(256, $x));
      }
    return $_return;
  }

//Теперь перейдем непосредственно у функции считывания полей и структуры таблицы
function open( $db_file ) {
    $this->info[name] = $db_file;
    $this->dbf = fopen($db_file, "rb+");
    fseek($this->dbf, 0);
    $this->info[memo] = ord(fread($this->dbf, 1));
    $date_access = fread($this->dbf, 3);
    $this->info[yy] = ord($date_access[0]) + 1900;
    $this->info[mm] = ord($date_access[1]);
    $this->info[dd] = ord($date_access[2]);
    $this->info[unix_timestamp] = mktime(0, 0, 0, $this->info[mm], $this->info[dd], $this->info[yy]);
    $this->info[records] = $this->_str2long(fread($this->dbf, 4));
    $this->info[header_size] = $this->_str2long(fread($this->dbf, 2));
    $this->info[record_size] = $this->_str2long(fread($this->dbf, 2));
    $this->info[reserved] = fread($this->dbf, 3);
    $this->info[reserved_network] = fread($this->dbf, 13);
    $this->info[reserved2] = fread($this->dbf, 4);

    $fields_data = fread($this->dbf, $this->info[header_size] - 33);
    $fields_data = wordwrap($fields_data, 32, "||", 1);
    $fields_data = explode("||", $fields_data);

    $_offseg = 1;
    while ($value = each($fields_data)) {
        $this->fields[$value[key]] = array(
            "name"   => trim(substr($value[value], 0, 11)),
            "type"   => substr($value[value], 11, 1),
            "size"   => $this->_str2long(substr($value[value], 16, 1)),
            "offseg" => $_offseg);

            $_offseg = $_offseg + $this->_str2long(substr($value[value], 16, 1));
      }
  }

//ну и наконец функция считывающая номер записи
function read_record( $recno ) {
    $_array = array();

    //Ставим указатель на начало запрашиваемой записи
    fseek($this->dbf, $this->info[header_size] + ($this->info[record_size] * ($recno - 1)));
    $_record_data = fread($this->dbf, $this->info[record_size]);
    $_record_flag = 1;
    while ($value = each($this->fields)) {
        $_array[$value[value][name]] = trim(substr($_record_data, $_record_flag, $value[value][size]));
        $_record_flag += $value[value][size];
      }
    reset($this->fields);
    return $_array;
  }

//Замена записи
function replace( $recno, $_in_array )	{
    $_array = array();
    while ($value = each($_in_array)) {
        while ($val_fields = each($this->fields)) {
            if ($val_fields[value][name] == $value[key]) {
                fseek($this->dbf, 0);
                $_offseg = $this->info[header_size] + ($this->info[record_size] * ($recno - 1)) + $val_fields[value][offseg];
                fseek($this->dbf, $_offseg);
                $value[value] = str_pad($value[value], $val_fields[value][size], chr(32), STR_PAD_RIGHT);
                fputs($this->dbf, $value[value], $val_fields[value][size]);
              }
          }
        reset($this->fields);
      }
    return $_array;
  }

//Закрывай файл, освобождаем переменные
function close() {
    fclose($this->dbf);
    unset($this->info, $this->fields);
  }
}

Вот получился у нас простенький класс для чтения записей формата dBase 4. Функций для создания таблиц, удаления и добавление записей я не делал, так как не было необходимости. Давайте рассмотрим теперь его использование, на примере, будем использовать справочник 1С - имя файла номенклатуры SC84.DBF или SC33.DBF:

//Подключаем класс
require_once("dbase.class.php");
//Создаем класс
$db = new dbase;
//Считываем заголовки и поля и таблицы
$db->open("SC84.DBF");
//Получаем количество записей в таблицы
$max_records = $db->info[records];
//Читаем каждую запись в массив, можно и сразу засунуть $db->info[records] в цикл
for ($x = 1; $x <= $max_records; $x++) {
    $row = $db->read_record($x); //Создает ассоциативный массив с именами и данными полей
  }
//Закрываем файл
$db->close();
Источник: © Vadikoff CO



© 2006 — 2019, Vadikoff CO, Блог v.1.6 on Core CMS ver. 1.0.10
Почта: mail@vadikoff.ru, Skype: vadikoff.ru, ICQ: 910-499
Core Dialog