dbf.lib.php
上传用户:jiangbw
上传日期:2022-03-16
资源大小:49k
文件大小:15k
- <?
- /*======================================================================*
- || #################################################################### ||
- || # BUILD UNDER PHP SCRIPTNET 3.2.1 FRAMEWORK ||
- || # ---------------------------------------------------------------- # ||
- || # Code2Art Open Source Software. All Rights Reserved. ||
- || # This file should be redistributed in whole or significant part. # ||
- || # ------------------ SCRIPTNET IS FREE SOFTWARE ------------------ # ||
- || # http://www.code2art.com | http://www.code2art.com/scriptnet # ||
- || # Copyleft by Benediktus Ardian Hersanto, SE # ||
- || # Sorry if this framework is still unavailable for public # ||
- || # because I still searching on my own head. # ||
- || #################################################################### ||
- *======================================================================*/
- /*======================================================================*
- || #################################################################### ||
- || DBF to MySQL Bulk Converter 2.0 ||
- ||______________________________________________________________________||
- || This utility was developed on 2006, since this were used to be on ||
- || my own library. But I think I should share it to you, because I ||
- || need to save my work on Internet (I don't believe on my own HD drive)||
- || it always crash and had a terrible bad sectors. ||
- || Thanks to all person who download this utility, I hope you enjoy it. ||
- || ||
- || Regards, ||
- || Benediktus Ardian Hersanto,SE (ardie_b@yahoo.com) ||
- /*======================================================================*/
- // ---------------------------------------------------------------------//
- // Free to use for everyone who understand PHP
- // ---------------------------------------------------------------------//
- /************************************************************
- author : B. Ardian Hersanto,SE on May 2006
- email : ardie_b@yahoo.com
- *************************************************************
- Thanks to http://www.wotsit.org for file type documentation.
- This script only works to PC only,
- on macintosh you have to change unpack format to big-endian (its your own problem, not me)
- *************************************************************/
- if(!function_exists('str_split')) {
- function str_split($string,$split_len=1) {
- $chars = array();
- for($i=0;$i<ceil(strlen($string)/$split_len);$i++)
- $chars[] = substr($string,$i*$split_len,$split_len);
- return $chars;
- }
- }
- class dbf {
-
- 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']
- var $check_validity = false;
- var $lowercase_fields = true;
- //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).
- var $date_format = array("Year","Month","Day"); //Standard date format
- var $dbase_iii = array(0x02,0x03,0x83); // Version types that match DBASE III structure has Different size on the length of Db Container Reserved area
- function dbf($filename) {
- echo "<CENTER>PROCESSING FILE : ",$filename,"<BR></CENTER>";
- if ( !file_exists($filename)) {
- echo 'DBF file not found!!!'; exit;
- } else $this->file = $filename;
- }
-
- function parseFile($read_contents=false) {
- //Read the File
- $filename = $this->file;
- $handle = fopen($filename, "r");
- if (!$handle) { echo "Cannot read DBF file"; exit; }
- $this->bin_data = fread($handle, filesize($filename));
- fclose ($handle);
- $this->version = hexdec(bin2hex($this->bin_data[0]));
- $this->table_type = $this->getTableType();
- if($this->table_type=='') die("Not a valid DBF file !!!");
- // Is a valid dbf file EOF signature
- $eof_signature = bin2hex(substr($this->bin_data,strlen($this->bin_data)-1,1));
- if($this->check_validity){if($eof_signature!='1a') die("Not a valid DBF file !!!");}
- $this->_struct = array();
- // Extract Date
- for($i=1; $i<4; $i++)
- $this->_struct['modified_date'][$this->date_format[-1+$i]] = bin2hex($this->bin_data[$i]);
- // Extract Number of records // V1 = little endian 32 bit read order
- $this->_struct['number_of_records'] = implode("",unpack("V1",substr($this->bin_data,4,4)));
- // Extract Length of header Structure // v1 = little endian 16 bit read order
- $this->_struct['header_length'] = implode("",unpack("v1",substr($this->bin_data,8,2)));
- // Extract Length of each record
- $this->_struct['each_rec_length'] = implode("",unpack("v1",substr($this->bin_data,10,2)));
- // Check if this file is not corrupted
- if($this->check_validity) {
- if($this->_struct['header_length']+($this->_struct['number_of_records']*$this->_struct['each_rec_length'])==filesize($filename)) die("File DBF Corrupt !!!");
- }
- // Extract Reserved
- $this->_struct['Reserved#1'] = implode("",unpack("v1",substr($this->bin_data,12,2)));
- // Extract Incomplete Transaction
- $this->_struct['Incomplete_Transaction'] = implode("",unpack("C1",substr($this->bin_data,14,1)));
- // Extract Encryption Flag
- $this->_struct['encryption_state'] = implode("",unpack("C1",substr($this->bin_data,15,1)));
- // Extract Reserved For LAN
- $this->_struct['LAN_reserved'] = implode("",unpack("V1",substr($this->bin_data,16,4)));
- // Extract Multi User DBASE
- $this->_struct['multi_user'] = implode("",unpack("V2",substr($this->bin_data,20,8)));
- // Extract MDX Flag
- $this->_struct['MDX_state'] = implode("",unpack("C1",substr($this->bin_data,28,1)));
- // Extract Language Driver
- $this->_struct['encode_language'] = bin2hex(substr($this->bin_data,29,1));
- // Extract Reserved 2nd
- $this->_struct['Reserved#2'] = bin2hex(substr($this->bin_data,30,2));
- // Extract Field Structures
- $end = '';$i=1; $this->data_offset = 0;
- if($this->_struct['number_of_records']>0) {
- while ($end=='') {
- $this->data_offset = $i*32;
- $tmp = bin2hex(substr($this->bin_data,$this->data_offset,32));
- if(eregi('0D',substr($tmp,0,2))) $end = '1';
- if($end=='')$this->_struct['Fields Raw'][] = $tmp;
- $i++;
- }
- $this->readStructure();
- if($read_contents) {
- if(eregi('Visual FoxPro',$this->table_type)) {
- // Extract Data
- $offset_start = $this->data_offset+264; // Database Container + 263 + 1 deleted record
- for($i=0;$i<$this->_struct['number_of_records'];$i++) {
- if($i>0) $offset_start = $this->_struct['each_rec_length']+$offset_start;
- $this->readData($offset_start,$i);
- }
- } else if(in_array($this->version,$this->dbase_iii)) {
- // Extract Data
- // There are some of software vendor add an empty char before data
- $header_bug_flag = bin2hex(substr($this->bin_data,$this->data_offset+1,1));
- if($header_bug_flag==0x00) $offset_start = $this->data_offset+2;
- else $offset_start = $this->data_offset+1; // Database Container + 1 deleted record
- for($i=0;$i<$this->_struct['number_of_records'];$i++) {
- if($i>0) $offset_start = $this->_struct['each_rec_length']+$offset_start;
- $this->readData($offset_start,$i);
- }
- }
- }
- }
- return $this->_struct;
- }
-
- function parseData() {
- if(eregi('Visual FoxPro',$this->table_type)) {
- // Extract Data
- $offset_start = $this->data_offset+264; // Database Container + 263 + 1 deleted record
- if($this->_struct['number_of_records']>0) {
- for($i=0;$i<$this->_struct['number_of_records'];$i++) {
- if($i>0) $offset_start = $this->_struct['each_rec_length']+$offset_start;
- $this->readData($offset_start,$i);
- }
- }
- } else if(in_array($this->version,$this->dbase_iii)) {
- // Extract Data
- // There are some of software vendor add an empty char before data
- $header_bug_flag = bin2hex(substr($this->bin_data,$this->data_offset+1,1));
- if($header_bug_flag==0x00) $offset_start = $this->data_offset+2;
- else $offset_start = $this->data_offset+1; // Database Container + 1 deleted record
- if($this->_struct['number_of_records']>0) {
- for($i=0;$i<$this->_struct['number_of_records'];$i++) {
- if($i>0) $offset_start = $this->_struct['each_rec_length']+$offset_start;
- $this->readData($offset_start,$i);
- }
- }
- }
- if(isset($this->_struct['Records'])&&is_array($this->_struct['Records']))
- return $this->_struct['Records']; else return NULL;
- }
-
- function readStructure() {
- if(isset($this->_struct['Fields Raw'])) {
- for($i=0;$i<count($this->_struct['Fields Raw']);$i++) {
- $row = $this->_struct['Fields Raw'][$i];
- // Extract Field Name
- $this->_struct['Fields'][$i]['Field Name'] = '';
- $string = substr($row,0,10*2);
- $chars = str_split($string,2);
- for($n=0;$n<count($chars);$n++)
- $this->_struct['Fields'][$i]['Field Name'] .= chr(hexdec($chars[$n]));
- if($this->lowercase_fields) $this->_struct['Fields'][$i]['Field Name'] = strtolower(trim($this->_struct['Fields'][$i]['Field Name']));
- // Extract Field Type
- $this->_struct['Fields'][$i]['Field Type'] = chr(hexdec(substr($row,11*2,1*2)));
- // Extract Field Data Address
- $this->_struct['Fields'][$i]['Field Data Address'] = substr($row,12*2,4*2);
- // Extract Field Length
- $this->_struct['Fields'][$i]['Field Length'] = hexdec(substr($row,16*2,1*2));
- // Extract Field Decimal Count
- $this->_struct['Fields'][$i]['Decimal Count'] = hexdec(substr($row,17*2,1*2));
- // Extract Multi User
- $this->_struct['Fields'][$i]['Multi User DBASE#1'] = substr($row,18*2,2*2);
- // Extract Work Area ID
- $this->_struct['Fields'][$i]['Work Area ID'] = substr($row,20*2,1*2);
- // Extract Reserved for Multi User
- $this->_struct['Fields'][$i]['Multi User DBASE#2'] = substr($row,21*2,2*2);
- // Extract Flag for SET FIELDS
- $this->_struct['Fields'][$i]['SET FIELDS FLAG'] = substr($row,23*2,1*2);
- // Extract Reserved
- $this->_struct['Fields'][$i]['Reserved'] = substr($row,24*2,7*2);
- // Extract Index Flag
- $this->_struct['Fields'][$i]['Index Field'] = substr($row,31*2,1*2);
- }
- unset($this->_struct['Fields Raw']);
- }
- }
-
- function readData($data_start,$index) {
- if(isset($this->_struct['Fields'])&&count($this->_struct['Fields'])>0) {
- $raw_hex = substr($this->bin_data,$data_start,$this->_struct['each_rec_length']);
- $prev_offset = 1;
- for($i=0;$i<count($this->_struct['Fields']);$i++) {
- $data_type = trim($this->_struct['Fields'][$i]['Field Type']);
- $column = trim($this->_struct['Fields'][$i]['Field Name']);
- $data_len = $this->_struct['Fields'][$i]['Field Length'];
- if(!isset($this->_struct['Records'][$index]['delete_mark']))$this->_struct['Records'][$index]['delete_mark'] = substr($raw_hex,0,1);
- $this->_struct['Records'][$index][$column] = $this->_ConvertDataType(substr($raw_hex,$prev_offset,$data_len),$this->_struct['Fields'][$i]);
- $prev_offset += $data_len;
- }
- } else die('Cannot read DBF data !!!');
- }
-
- function _ConvertDataType($content,$_def) {
- $type = $_def['Field Type'];
- switch ($type) {
- case 'C' : return $content; break;
- case 'L' : if(eregi('T',$content)||eregi('Y',$content)) return TRUE;
- else if(eregi('F',$content)||eregi('N',$content)) return FALSE;
- else return NULL;
- break;
- case 'D' : $date['Year'] = trim(substr($content,0,4));
- $date['Month'] = trim(substr($content,4,2));
- $date['Day'] = trim(substr($content,6,2));
- return $date;
- break;
- case 'N' : if($_def['Decimal Count']==0) settype($content,"integer");
- return $content;
- break;
- case 'M' : return $this->readMemo($_def); break;
- }
- }
-
- function createMySQLTable() {
- $file = basename($this->file);
- $table_name = eregi_replace(".dbf",'',$file);
- $sql = "CREATE TABLE IF NOT EXISTS {$table_name}(";
- if(isset($this->_struct['Fields'])&&is_array($this->_struct['Fields'])) {
- for($i=0;$i<count($this->_struct['Fields']);$i++) {
- if($this->lowercase_fields) $field_name = strtolower($this->_struct['Fields'][$i]['Field Name']);
- else $field_name = $this->_struct['Fields'][$i]['Field Name'];
- $fields[] = trim($field_name).$this->getMySQLDataType($this->_struct['Fields'][$i]);
- }
- $sql .= implode(',',$fields).")";
- return $sql;
- } else {
- return '';
- }
- }
-
- function getMySQLDataType($_def) {
- $type = $_def['Field Type'];
- switch ($type) {
- case 'C' : if($_def['Field Length']>5) return " varchar(".$_def['Field Length'].")"; else return " char(".$_def['Field Length'].")";break;
- case 'L' : return " int(1) default 0";
- break;
- case 'D' : return " date";
- break;
- case 'N' : if($_def['Decimal Count']==0) return " int(".$_def['Field Length'].")";
- else if($_def['Decimal Count']>0) return " float(".$_def['Field Length'].",".$_def['Decimal Count'].")";
- break;
- case 'M' : return " text"; break;
- }
- }
-
- function readMemo($_def) {
- if(eregi('Fox',$this->table_type)) $memo = basename(basename($this->file,".dbf"),".DBF").".fpt";
- else $memo = basename(basename($this->file,".dbf"),".DBF").".dbt";
- if(file_exists($memo)) {
- $fp = fopen($memo,"r");
- if($fp) {
- $mem_file = fread($fp,filesize($memo));
- // Read Header
- $index = (isset($this->_struct['Memo']))?count($this->_struct['Memo']):0;
- if(eregi('Fox',$this->table_type)) {
- $memo_header = substr($mem_file,0,512);
- $memo_text = substr($mem_file,512,filesize($memo));
- //Number of next available Block skipped
- //bin2hex(implode("",unpack("N1",substr($memo_header,0,4))));
- $size_of_block = hexdec(bin2hex(substr($memo_header,6,2)));
- $start_offset = isset($this->_struct['Memo'][$index-1])?$size_of_block*$index:0;
- $this->_struct['Memo'][$index]['Record Type'] = bin2hex(substr($memo_text,$start_offset+3,1));
- $this->_struct['Memo'][$index]['Length of Memo'] = hexdec(bin2hex(substr($memo_text,$start_offset+4,4)));
- $this->_struct['Memo'][$index]['Content'] = substr($memo_text,$start_offset+8,$this->_struct['Memo'][$index]['Length of Memo']);
- fclose($fp);
- return $this->_struct['Memo'][$index]['Content'];
- }
- } else {
- echo "<b>Warning :</b> File permission denied on file ".$memo."<BR>";
- fclose($fp);
- }
- } else {
- echo "<b>Warning :</b> Memo file not found!!!<br>";
- }
- }
-
- function getTableType() {
- settype($this->version,"integer");
- switch ($this->version) {
- case 2 : return "FoxBase"; break;
- case 3 : return "File without DBT"; break;
- case 4 : return "dBASE IV w/o memo file"; break;
- case 5 : return "dBASE V w/o memo file"; break;
- case 48 : return "Visual FoxPro w. DBC"; break;
- case 49 : return "Visual FoxPro w. AutoIncrement field"; break;
- case 67 : return ".dbv memo var size (Flagship)"; break;
- case 123 : return "dBASE IV with memo"; break;
- case 131 : return "File with DBT or dBASE III+ with memo file"; break;
- case 139 : return "dBASE IV w. memo"; break;
- case 142 : return "dBASE IV w. SQL table"; break;
- case 179 : return ".dbv and .dbt memo (Flagship)"; break;
- case 229 : return "Clipper SIX driver w. SMT memo file."; break;
- case 245 : return "FoxPro w. memo file"; break;
- case 251 : return "Unknown Foxpro"; break;
- }
- }
- }
- ?>