VPS主机
测评与优惠

PHP读取dbf数据库时dbase无法读取字段类型为memo的数据的解决办法

自定义的php dbf读取类:

  class Prodigy_DBF {      private $Filename, $DB_Type, $DB_Update, $DB_Records, $DB_FirstData, $DB_RecordLength, $DB_Flags, $DB_CodePageMark, $DB_Fields, $FileHandle, $FileOpened;      private $Memo_Handle, $Memo_Opened, $Memo_BlockSize;        private function Initialize() {            if($this->FileOpened) {              fclose($this->FileHandle);          }            if($this->Memo_Opened) {              fclose($this->Memo_Handle);          }            $this->FileOpened = false;          $this->FileHandle = NULL;          $this->Filename = NULL;          $this->DB_Type = NULL;          $this->DB_Update = NULL;          $this->DB_Records = NULL;          $this->DB_FirstData = NULL;          $this->DB_RecordLength = NULL;          $this->DB_CodePageMark = NULL;          $this->DB_Flags = NULL;          $this->DB_Fields = array();            $this->Memo_Handle = NULL;          $this->Memo_Opened = false;          $this->Memo_BlockSize = NULL;      }        public function __construct($Filename, $MemoFilename = NULL) {          $this->Prodigy_DBF($Filename, $MemoFilename);      }        public function Prodigy_DBF($Filename, $MemoFilename = NULL) {          $this->Initialize();          $this->OpenDatabase($Filename, $MemoFilename);      }        public function OpenDatabase($Filename, $MemoFilename = NULL) {          $Return = false;          $this->Initialize();            $this->FileHandle = fopen($Filename, "r");          if($this->FileHandle) {              // DB Open, reading headers              $this->DB_Type = dechex(ord(fread($this->FileHandle, 1)));              $LUPD = fread($this->FileHandle, 3);              $this->DB_Update = ord($LUPD[0])."/".ord($LUPD[1])."/".ord($LUPD[2]);              $Rec = unpack("V", fread($this->FileHandle, 4));              $this->DB_Records = $Rec[1];              $Pos = fread($this->FileHandle, 2);              $this->DB_FirstData = (ord($Pos[0]) + ord($Pos[1]) * 256);              $Len = fread($this->FileHandle, 2);              $this->DB_RecordLength = (ord($Len[0]) + ord($Len[1]) * 256);              fseek($this->FileHandle, 28); // Ignoring "reserved" bytes, jumping to table flags              $this->DB_Flags = dechex(ord(fread($this->FileHandle, 1)));              $this->DB_CodePageMark = ord(fread($this->FileHandle, 1));              fseek($this->FileHandle, 2, SEEK_CUR);    // Ignoring next 2 "reserved" bytes                // Now reading field captions and attributes              while(!feof($this->FileHandle)) {                    // Checking for end of header                  if(ord(fread($this->FileHandle, 1)) == 13) {                      break;  // End of header!                  } else {                      // Go back                      fseek($this->FileHandle, -1, SEEK_CUR);                  }                    $Field["Name"] = trim(fread($this->FileHandle, 11));                  $Field["Type"] = fread($this->FileHandle, 1);                  fseek($this->FileHandle, 4, SEEK_CUR);  // Skipping attribute "displacement"                  $Field["Size"] = ord(fread($this->FileHandle, 1));                  fseek($this->FileHandle, 15, SEEK_CUR); // Skipping any remaining attributes                  $this->DB_Fields[] = $Field;              }                // Setting file pointer to the first record              fseek($this->FileHandle, $this->DB_FirstData);                $this->FileOpened = true;                // Open memo file, if exists              if(!empty($MemoFilename) and file_exists($MemoFilename) and preg_match("%^(.+).fpt$%i", $MemoFilename)) {                  $this->Memo_Handle = fopen($MemoFilename, "r");                  if($this->Memo_Handle) {                      $this->Memo_Opened = true;                        // Getting block size                      fseek($this->Memo_Handle, 6);                      $Data = unpack("n", fread($this->Memo_Handle, 2));                      $this->Memo_BlockSize = $Data[1];                  }              }          }            return $Return;      }        public function GetNextRecord($FieldCaptions = false) {          $Return = NULL;          $Record = array();            if(!$this->FileOpened) {              $Return = false;          } elseif(feof($this->FileHandle)) {              $Return = NULL;          } else {              // File open and not EOF              fseek($this->FileHandle, 1, SEEK_CUR);  // Ignoring DELETE flag              foreach($this->DB_Fields as $Field) {                  $RawData = fread($this->FileHandle, $Field["Size"]);                  // Checking for memo reference                  if($Field["Type"] == "M" and $Field["Size"] == 4 and !empty($RawData)) {                      // Binary Memo reference                      $Memo_BO = unpack("V", $RawData);                      if($this->Memo_Opened and $Memo_BO != 0) {                          fseek($this->Memo_Handle, $Memo_BO[1] * $this->Memo_BlockSize);                          $Type = unpack("N", fread($this->Memo_Handle, 4));                          if($Type[1] == "1") {                              $Len = unpack("N", fread($this->Memo_Handle, 4));                              $Value = trim(fread($this->Memo_Handle, $Len[1]));                          } else {                              // Pictures will not be shown                              $Value = "{BINARY_PICTURE}";                          }                      } else {                          $Value = "{NO_MEMO_FILE_OPEN}";                      }                  } else {                      $Value = trim($RawData);                  }                    if($FieldCaptions) {                      $Record[$Field["Name"]] = $Value;                  } else {                      $Record[] = $Value;                  }              }                $Return = $Record;          }            return $Return;      }        function __destruct() {          // Cleanly close any open files before destruction          $this->Initialize();      }  }  

使用方法:

  $Test = new Prodigy_DBF("customer.DBF", "customer.FPT");  while(($Record = $Test->GetNextRecord(true)) and !empty($Record)) {      print_r($Record);  }  

参数1为dbf文件路径,参数2为fpt文件路径(可省略)。

注意事项:

It might not be an almighty perfect class, but it works for me. Feel free to use this code, but note that the class is VERY tolerant – it doesn't care if fread() and fseek() return true or anything else – so you might want to improve it a bit before using.

Also note that there are many private variables like number of records, recordsize etc. which are not used at the moment.

原贴网址:

http://stackoverflow.com/questions/1947348/how-to-read-foxpro-memo-with-php

赞(0)
未经允许不得转载:主机之家测评 » PHP读取dbf数据库时dbase无法读取字段类型为memo的数据的解决办法

评论 抢沙发

评论前必须登录!

立即登录   注册