api.dbf.php 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. <?php
  2. /**
  3. *
  4. * DBF reader Class v0.04 by Faro K Rasyid (Orca)
  5. orca75_at_dotgeek_dot_org
  6. v0.05 by Nicholas Vrtis
  7. vrtis_at_vrtisworks_dot_com
  8. 1) changed to not read in complete file at creation.
  9. 2) added function to read individual rows
  10. 3) added support for Memo fields in dbt files.
  11. 4) See: http://www.clicketyclick.dk/databases/xbase/format/dbf.html#DBF_STRUCT
  12. for some additional information on XBase structure...
  13. 5) NOTE: the whole file (and the memo file) is read in at once. So this could
  14. take a lot of memory for large files.
  15. Input : name of the DBF( dBase III plus) file
  16. Output : - dbf_num_rec, the number of records
  17. - dbf_num_field, the number of fields
  18. - dbf_names, array of field information ('name', 'len', 'type')
  19. Usage example:
  20. $file= "your_file.dbf";//WARNING !!! CASE SENSITIVE APPLIED !!!!!
  21. $dbf = new dbf_class($file);
  22. $num_rec=$dbf->dbf_num_rec;
  23. $num_field=$dbf->dbf_num_field;
  24. for($i=0; $i<$num_rec; $i++){
  25. $row = $dbf->getRow($i);
  26. for($j=0; $j<$num_field; $j++){
  27. echo $row[$j].' ');
  28. }
  29. echo('<br>');
  30. }
  31. Thanks to :
  32. - Willy
  33. - Miryadi
  34. This library is free software; you can redistribute it and/or
  35. modify it under the terms of the GNU Lesser General Public
  36. License as published by the Free Software Foundation; either
  37. version 2.1 of the License, or (at your option) any later version.
  38. This library is distributed in the hope that it will be useful,
  39. but WITHOUT ANY WARRANTY; without even the implied warranty of
  40. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  41. See the GNU Lesser General Public License for more details.
  42. */
  43. class dbf_class {
  44. var $dbf_num_rec; //Number of records in the file
  45. var $dbf_num_field; //Number of columns in each row
  46. var $dbf_names = array(); //Information on each column ['name'],['len'],['type']
  47. //These are private....
  48. var $_raw; //The raw input file
  49. var $_rowsize; //Length of each row
  50. var $_hdrsize; //Length of the header information (offset to 1st record)
  51. var $_memos; //The raw memo file (if there is one).
  52. public function __construct($filename) {
  53. if (!file_exists($filename)) {
  54. show_error('Not a valid DBF file !!!');
  55. exit;
  56. }
  57. $tail = substr($filename, -4);
  58. if (strcasecmp($tail, '.dbf') != 0) {
  59. show_error('Not a valid DBF file !!!');
  60. exit;
  61. }
  62. //Read the File
  63. $handle = fopen($filename, "r");
  64. if (!$handle) {
  65. show_error('Cannot read DBF file !!!');
  66. exit;
  67. }
  68. $filesize = filesize($filename);
  69. $this->_raw = fread($handle, $filesize);
  70. fclose($handle);
  71. //Make sure that we indeed have a dbf file...
  72. if (!(ord($this->_raw[0]) == 3 || ord($this->_raw[0]) == 131) && ord($this->_raw[$filesize]) != 26) {
  73. show_error('Not a valid DBF file !!!');
  74. exit;
  75. }
  76. // 3= file without DBT memo file; 131 ($83)= file with a DBT.
  77. $arrHeaderHex = array();
  78. for ($i = 0; $i < 32; $i++) {
  79. $arrHeaderHex[$i] = str_pad(dechex(ord($this->_raw[$i])), 2, "0", STR_PAD_LEFT);
  80. }
  81. //Initial information
  82. $line = 32; //Header Size
  83. //Number of records
  84. $this->dbf_num_rec = hexdec($arrHeaderHex[7] . $arrHeaderHex[6] . $arrHeaderHex[5] . $arrHeaderHex[4]);
  85. $this->_hdrsize = hexdec($arrHeaderHex[9] . $arrHeaderHex[8]); //Header Size+Field Descriptor
  86. //Number of fields
  87. $this->_rowsize = hexdec($arrHeaderHex[11] . $arrHeaderHex[10]);
  88. $this->dbf_num_field = floor(($this->_hdrsize - $line ) / $line); //Number of Fields
  89. //Field properties retrieval looping
  90. for ($j = 0; $j < $this->dbf_num_field; $j++) {
  91. $name = '';
  92. $beg = $j * $line + $line;
  93. for ($k = $beg; $k < $beg + 11; $k++) {
  94. if (ord($this->_raw[$k]) != 0) {
  95. $name .= $this->_raw[$k];
  96. }
  97. }
  98. $this->dbf_names[$j]['name'] = $name; //Name of the Field
  99. $this->dbf_names[$j]['len'] = ord($this->_raw[$beg + 16]); //Length of the field
  100. $this->dbf_names[$j]['type'] = $this->_raw[$beg + 11];
  101. }
  102. if (ord($this->_raw[0]) == 131) { //See if this has a memo file with it...
  103. //Read the File
  104. $tail = substr($tail, -1, 1); //Get the last character...
  105. if ($tail == 'F') { //See if upper or lower case
  106. $tail = 'T'; //Keep the case the same
  107. } else {
  108. $tail = 't';
  109. }
  110. $memoname = substr($filename, 0, strlen($filename) - 1) . $tail;
  111. $handle = fopen($memoname, "r");
  112. if (!$handle) {
  113. show_error('Cannot read DBT file !!!');
  114. exit;
  115. }
  116. $filesize = filesize($memoname);
  117. $this->_memos = fread($handle, $filesize);
  118. fclose($handle);
  119. }
  120. }
  121. function getRow($recnum) {
  122. $memoeot = chr(26) . chr(26);
  123. $rawrow = substr($this->_raw, $recnum * $this->_rowsize + $this->_hdrsize, $this->_rowsize);
  124. $rowrecs = array();
  125. $beg = 1;
  126. if (ord($rawrow[0]) == 42) {
  127. return false; //Record is deleted...
  128. }
  129. for ($i = 0; $i < $this->dbf_num_field; $i++) {
  130. $col = trim(substr($rawrow, $beg, $this->dbf_names[$i]['len']));
  131. if ($this->dbf_names[$i]['type'] != 'M') {
  132. $rowrecs[] = $col;
  133. } else {
  134. $memobeg = $col * 512; //Find start of the memo block (0=header so it works)
  135. $memoend = strpos($this->_memos, $memoeot, $memobeg); //Find the end of the memo
  136. $rowrecs[] = substr($this->_memos, $memobeg, $memoend - $memobeg);
  137. }
  138. $beg += $this->dbf_names[$i]['len'];
  139. }
  140. return $rowrecs;
  141. }
  142. function getRowAssoc($recnum) {
  143. $memoeot = chr(26) . chr(26);
  144. $rawrow = substr($this->_raw, $recnum * $this->_rowsize + $this->_hdrsize, $this->_rowsize);
  145. $rowrecs = array();
  146. $beg = 1;
  147. if (ord($rawrow[0]) == 42) {
  148. return false; //Record is deleted...
  149. }
  150. for ($i = 0; $i < $this->dbf_num_field; $i++) {
  151. $col = trim(substr($rawrow, $beg, $this->dbf_names[$i]['len']));
  152. if ($this->dbf_names[$i]['type'] != 'M') {
  153. $rowrecs[$this->dbf_names[$i]['name']] = $col;
  154. } else {
  155. $memobeg = $col * 512; //Find start of the memo block (0=header so it works)
  156. $memoend = strpos($this->_memos, $memoeot, $memobeg); //Find the end of the memo
  157. $rowrecs[$this->dbf_names[$i]['name']] = substr($this->_memos, $memobeg, $memoend - $memobeg);
  158. }
  159. $beg += $this->dbf_names[$i]['len'];
  160. }
  161. return $rowrecs;
  162. }
  163. }
  164. //End of Class
  165. ?>