123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- <?php
- /**
- *
- * DBF reader Class v0.04 by Faro K Rasyid (Orca)
- orca75_at_dotgeek_dot_org
- v0.05 by Nicholas Vrtis
- vrtis_at_vrtisworks_dot_com
- 1) changed to not read in complete file at creation.
- 2) added function to read individual rows
- 3) added support for Memo fields in dbt files.
- 4) See: http://www.clicketyclick.dk/databases/xbase/format/dbf.html#DBF_STRUCT
- for some additional information on XBase structure...
- 5) NOTE: the whole file (and the memo file) is read in at once. So this could
- take a lot of memory for large files.
- Input : name of the DBF( dBase III plus) file
- Output : - dbf_num_rec, the number of records
- - dbf_num_field, the number of fields
- - dbf_names, array of field information ('name', 'len', 'type')
- Usage example:
- $file= "your_file.dbf";//WARNING !!! CASE SENSITIVE APPLIED !!!!!
- $dbf = new dbf_class($file);
- $num_rec=$dbf->dbf_num_rec;
- $num_field=$dbf->dbf_num_field;
- for($i=0; $i<$num_rec; $i++){
- $row = $dbf->getRow($i);
- for($j=0; $j<$num_field; $j++){
- echo $row[$j].' ');
- }
- echo('<br>');
- }
- Thanks to :
- - Willy
- - Miryadi
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU Lesser General Public License for more details.
- */
- class dbf_class {
- var $dbf_num_rec; //Number of records in the file
- var $dbf_num_field; //Number of columns in each row
- var $dbf_names = array(); //Information on each column ['name'],['len'],['type']
- //These are private....
- var $_raw; //The raw input file
- var $_rowsize; //Length of each row
- var $_hdrsize; //Length of the header information (offset to 1st record)
- var $_memos; //The raw memo file (if there is one).
- public function __construct($filename) {
- if (!file_exists($filename)) {
- show_error('Not a valid DBF file !!!');
- exit;
- }
- $tail = substr($filename, -4);
- if (strcasecmp($tail, '.dbf') != 0) {
- show_error('Not a valid DBF file !!!');
- exit;
- }
- //Read the File
- $handle = fopen($filename, "r");
- if (!$handle) {
- show_error('Cannot read DBF file !!!');
- exit;
- }
- $filesize = filesize($filename);
- $this->_raw = fread($handle, $filesize);
- fclose($handle);
- //Make sure that we indeed have a dbf file...
- if (!(ord($this->_raw[0]) == 3 || ord($this->_raw[0]) == 131) && ord($this->_raw[$filesize]) != 26) {
- show_error('Not a valid DBF file !!!');
- exit;
- }
- // 3= file without DBT memo file; 131 ($83)= file with a DBT.
- $arrHeaderHex = array();
- for ($i = 0; $i < 32; $i++) {
- $arrHeaderHex[$i] = str_pad(dechex(ord($this->_raw[$i])), 2, "0", STR_PAD_LEFT);
- }
- //Initial information
- $line = 32; //Header Size
- //Number of records
- $this->dbf_num_rec = hexdec($arrHeaderHex[7] . $arrHeaderHex[6] . $arrHeaderHex[5] . $arrHeaderHex[4]);
- $this->_hdrsize = hexdec($arrHeaderHex[9] . $arrHeaderHex[8]); //Header Size+Field Descriptor
- //Number of fields
- $this->_rowsize = hexdec($arrHeaderHex[11] . $arrHeaderHex[10]);
- $this->dbf_num_field = floor(($this->_hdrsize - $line ) / $line); //Number of Fields
- //Field properties retrieval looping
- for ($j = 0; $j < $this->dbf_num_field; $j++) {
- $name = '';
- $beg = $j * $line + $line;
- for ($k = $beg; $k < $beg + 11; $k++) {
- if (ord($this->_raw[$k]) != 0) {
- $name .= $this->_raw[$k];
- }
- }
- $this->dbf_names[$j]['name'] = $name; //Name of the Field
- $this->dbf_names[$j]['len'] = ord($this->_raw[$beg + 16]); //Length of the field
- $this->dbf_names[$j]['type'] = $this->_raw[$beg + 11];
- }
- if (ord($this->_raw[0]) == 131) { //See if this has a memo file with it...
- //Read the File
- $tail = substr($tail, -1, 1); //Get the last character...
- if ($tail == 'F') { //See if upper or lower case
- $tail = 'T'; //Keep the case the same
- } else {
- $tail = 't';
- }
- $memoname = substr($filename, 0, strlen($filename) - 1) . $tail;
- $handle = fopen($memoname, "r");
- if (!$handle) {
- show_error('Cannot read DBT file !!!');
- exit;
- }
- $filesize = filesize($memoname);
- $this->_memos = fread($handle, $filesize);
- fclose($handle);
- }
- }
- function getRow($recnum) {
- $memoeot = chr(26) . chr(26);
- $rawrow = substr($this->_raw, $recnum * $this->_rowsize + $this->_hdrsize, $this->_rowsize);
- $rowrecs = array();
- $beg = 1;
- if (ord($rawrow[0]) == 42) {
- return false; //Record is deleted...
- }
- for ($i = 0; $i < $this->dbf_num_field; $i++) {
- $col = trim(substr($rawrow, $beg, $this->dbf_names[$i]['len']));
- if ($this->dbf_names[$i]['type'] != 'M') {
- $rowrecs[] = $col;
- } else {
- $memobeg = $col * 512; //Find start of the memo block (0=header so it works)
- $memoend = strpos($this->_memos, $memoeot, $memobeg); //Find the end of the memo
- $rowrecs[] = substr($this->_memos, $memobeg, $memoend - $memobeg);
- }
- $beg += $this->dbf_names[$i]['len'];
- }
- return $rowrecs;
- }
- function getRowAssoc($recnum) {
- $memoeot = chr(26) . chr(26);
- $rawrow = substr($this->_raw, $recnum * $this->_rowsize + $this->_hdrsize, $this->_rowsize);
- $rowrecs = array();
- $beg = 1;
- if (ord($rawrow[0]) == 42) {
- return false; //Record is deleted...
- }
- for ($i = 0; $i < $this->dbf_num_field; $i++) {
- $col = trim(substr($rawrow, $beg, $this->dbf_names[$i]['len']));
- if ($this->dbf_names[$i]['type'] != 'M') {
- $rowrecs[$this->dbf_names[$i]['name']] = $col;
- } else {
- $memobeg = $col * 512; //Find start of the memo block (0=header so it works)
- $memoend = strpos($this->_memos, $memoeot, $memobeg); //Find the end of the memo
- $rowrecs[$this->dbf_names[$i]['name']] = substr($this->_memos, $memobeg, $memoend - $memobeg);
- }
- $beg += $this->dbf_names[$i]['len'];
- }
- return $rowrecs;
- }
- }
- //End of Class
- ?>
|