SitePoint Sponsor

User Tag List

Results 1 to 7 of 7

Hybrid View

  1. #1
    That's Right. notepad_coder's Avatar
    Join Date
    Apr 2002
    Location
    Colorado
    Posts
    835
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Problems with the file functions.

    I have a class, File, which handles file functions... I have File::replace($old, $new); which is working fine, but when I go to File::read(); after replace() is called, it wont output the file contents... Any ideas as to why?

    Code PHP:
    public function replace($old, $new, $all = false) {
        $pointer = $this->find($old, true);
        $tmp_name = $this->file.".tmp";
        $tmp = new File($tmp_name, $this->binary);
        $tmp->truncate(0);
        $tmp->write($this->read(($pointer + strlen($old)), $this->size));
        $this->truncate($pointer);
        $this->write($new);
        $this->write($tmp->read());
        $tmp->delete();
        if ($all && strpos($this->read(), $old)) {
            return $this->replace($old, $new, $all);
        } else {
            return true;
        }
    }
     
    $f = new File("file.txt");
     
    $f->truncate(0);
    $f->write("some text.");
     
    echo $f->read();
     
    $f->replace("text", "more text");
     
    echo $f->read();

    there is no output... But file.txt when opened in a text editor says "some more text"

    Any help would be greatly appreciated.

    Also, I am reloading the file stream... I thought maybe that would do it, but nothing...

    Code php:
    public function write($data, $pos = null) {
        // calls File::reloadFile() after fwrite();
    }
     
    public function truncate($from = 0, $to = null) {
        // calls File::reloadFile() after ftruncate();
    }
     
    private function reloadFile() {
        fclose($this->fp);
        $mode = "a+";
        if ($this->binary) {
            $mode .= "b";
        }
        $this->fp = fopen($this->file, $mode);
        $this->details(null, true);
    }
    - the lid is off the maple syrup again!

  2. #2
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2008
    Posts
    5,757
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Could you post the entire class?

  3. #3
    That's Right. notepad_coder's Avatar
    Join Date
    Apr 2002
    Location
    Colorado
    Posts
    835
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The class is 313 lines, so here are the methods being used:

    PHP Code:
    class File {

        public function 
    __construct($file$binary FILE_NOT_BINARY) {
            
    $this->file $file;
            
    $this->binary $binary;
            if (!
    Open_Files::open($this->file)) {
                
    $this->kill("File '".$this->file."' is already loaded.");
            }
            if (!
    $this->exists()) {
                
    $this->error("File '".$this->file."' does not exist.");
            }
            
    $mode "a+";
            if (
    $this->binary) {
                
    $mode .= "b";
            }
            if ((
    $this->fp = @fopen($this->file$mode)) === false) {
                
    $this->error("File could not be opened or created. Please check file/folder permissions.");
            }
            
    $this->details();
        }

        
    /***/

        
    public function read($from 0$to null) {
            if (!
    is_int($from)) {
                
    $this->error("File::read(\$from) must be an int.");
            }
            
    $this->pointer($from);
            if (
    is_null($to)) {
                
    $data "";
                do {
                    
    $data .= @fread($this->fp4096);
                } while (!
    feof($this->fp));
            } else {
                if (!
    is_int($to)) {
                    
    $this->error("File::read(\$to) must be an int.");
                }
                
    $data = @fread($this->fp$to);
            }
            return 
    $data;
        }

        public function 
    find($data$pointer false$reset false) {
            static 
    $offset 0;
            if (
    $reset) {
                
    $offset 0;
            }
            if ((
    $pos strpos($this->read(), $data$offset)) !== false) {
                
    $offset++;
                return (!
    $pointer) ? true $pos;
            } else {
                return 
    false;
            }
        }

        public function 
    write($data$pos null) {
            if (!
    is_null($pos) && !is_int($pos)) {
                
    $this->error("File::write(\$pos) must be an int.");
            }
            if (!
    is_null($pos)) {
                
    $this->pointer($pos);
            }
            if (!empty(
    $data) && (strlen($data) != 0)) {
                @
    fwrite($this->fp$data);
                
    $this->reloadFile();
            }
        }

        public function 
    replace($old$new$all false) {
            
    $pointer $this->find($oldtrue);
            
    $tmp_name $this->file.".tmp";
            
    $tmp = new File($tmp_name$this->binary);
            
    $tmp->truncate(0);
            
    $tmp->write($this->read(($pointer strlen($old)), $this->size));
            
    $this->truncate($pointer);
            
    $this->write($new.$tmp->read());
            
    $tmp->delete();
            if (
    $all && strpos($this->read(), $old)) {
                return 
    $this->replace($old$new$all);
            } else {
                return 
    true;
            }
        }

        public function 
    truncate($from 0) {
            if (!
    is_int($from)) {
                
    $this->error("File::truncate(\$from) must be an int.");
            }
            if (
    $from $this->size) {
                
    $from $this->size;
            }
            
    $this->pointer($from);
            @
    ftruncate($this->fp$from);
            
    $this->reloadFile();
        }

        public function 
    delete() {
            
    $this->unlock();
            @
    fclose($this->fp);
            @
    ulink($this->file);
            
    $this->__destruct();
        }

        private function 
    reloadFile() {
            
    fclose($this->fp);
            
    $mode "a+";
            if (
    $this->binary) {
                
    $mode .= "b";
            }
            
    $this->fp fopen($this->file$mode);
            
    $this->details(nulltrue);
        }

        
    /***/

        
    private function __destruct() {
            
    Open_Files::close($this->file);
            if (
    is_resource($this->fp)) {
                @
    fclose($this->fp);
            }
        }

    - the lid is off the maple syrup again!

  4. #4
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2008
    Posts
    5,757
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I was hoping to be able to run the code to make debugging easier, but it's still incomplete, and altered. My guess would be the undisclosed position() method doesn't properly fseek() on the fp. Without a fseek() or rewind(), you will be reading from the end of the file due to using a+ mode.

  5. #5
    That's Right. notepad_coder's Avatar
    Join Date
    Apr 2002
    Location
    Colorado
    Posts
    835
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    File:ointer runs fseek()

    PHP Code:
        private function pointer($offset null) {
            if (
    is_null($offset)) {
                return 
    ftell($this->fp);
            } else {
                return 
    fseek($this->fp$offset);
            }
        } 
    Here is the class

    PHP Code:

    define
    ("FILE_NOT_BINARY"0);

    define("FILE_IS_BINARY"1);

    class 
    File {

        protected 
    $file;

        protected 
    $size = -1;

        protected 
    $details = array();

        private 
    $fp false;

        private 
    $locked false;

        private 
    $binary false;

        private 
    $debug true;

        public function 
    __construct($file$binary FILE_NOT_BINARY) {
            
    $this->file $file;
            
    $this->binary $binary;
            if (!
    Open_Files::open($this->file)) {
                
    $this->kill("File '".$this->file."' is already loaded.");
            }
            if (!
    $this->exists()) {
                
    $this->error("File '".$this->file."' does not exist.");
            }
            
    $mode "a+";
            if (
    $this->binary) {
                
    $mode .= "b";
            }
            if ((
    $this->fp = @fopen($this->file$mode)) === false) {
                
    $this->error("File could not be opened or created. Please check file/folder permissions.");
            }
            
    $this->details();
        }

        public function 
    __destruct() {
            
    Open_Files::close($this->file);
            if (
    is_resource($this->fp)) {
                @
    fclose($this->fp);
            }
        }

        public function 
    debug($debug) {
            
    $this->debug $debug;
        }

        public function 
    details($detail null$reload false) {
            if (
    is_null($detail)) {
                if (empty(
    $this->details) || $reload) {
                    
    $pathinfo pathinfo($this->file);
                    
    $details = array();
                    
    $details['filename']   = $pathinfo['basename'];
                    
    $details['extension']  = $pathinfo['extension'];
                    
    $details['filesize']   = filesize($this->file);
                    
    $details['directory']  = $pathinfo['dirname'];
                    
    $details['created']    = filectime($this->file);
                    
    $details['accessed']   = fileatime($this->file);
                    
    $details['modified']   = filemtime($this->file);
                    
    $details['md5_sum']    = md5_file($this->file);
                    
    $details['sha1_sum']   = sha1_file($this->file);
                    
    $this->details $details;
                    
    $this->size $this->details['filesize'];
                }
            } else {
                if (
    in_array($detail$this->details)) {
                    return 
    $this->details[$detail];
                } else {
                    
    $this->alert("The file detail requested was not available.");
                }
            }
        }

        public function 
    permissions($mode) {
            if (!@
    chmod($this->file$mode)) {
                
    $this->alert("The file permissions are not allowed to be change.");
            }
        }

        public function 
    read($from 0$to null) {
            if (!
    is_int($from)) {
                
    $this->error("Supplied arguments for File::read() must be ints.");
            }
            
    $this->pointer($from);
            if (
    is_null($to)) {
                
    $data "";
                do {
                    
    $data .= @fread($this->fp4096);
                } while (!
    feof($this->fp));
            } else {
                if (!
    is_int($to)) {
                    
    $this->error("Supplied arguments for File::read() must be ints.");
                }
                
    $data = @fread($this->fp$to);
            }
            return 
    $data;
        }

        public function 
    find($data$pointer false$reset false) {
            static 
    $offset 0;
            if (
    $reset) {
                
    $offset 0;
            }
            if ((
    $pos strpos($this->read(), $data$offset)) !== false) {
                
    $offset++;
                return (!
    $pointer) ? true $pos;
            } else {
                return 
    false;
            }
        }

        public function 
    write($data$pos null) {
            if (!
    is_null($pos) && !is_int($pos)) {
                
    $this->error("Supplied argument (\$pos) for File::write() must be an int.");
            }
            if (!
    is_null($pos)) {
                
    $this->pointer($pos);
            }
            if (!empty(
    $data) && (strlen($data) != 0)) {
                @
    fwrite($this->fp$data);
                
    $this->reloadFile();
            }
        }

        public function 
    replace($old$new$all false) {
            
    $pointer $this->find($oldtrue);
            
    $tmp_name $this->file.".tmp";
            
    $tmp = new File($tmp_name$this->binary);
            
    $tmp->truncate(0);
            
    $tmp->write($this->read(($pointer strlen($old)), $this->size));
            
    $this->truncate($pointer);
            
    $this->write($new.$tmp->read());
            
    $tmp->delete();
            if (
    $all && strpos($this->read(), $old)) {
                return 
    $this->replace($old$new$all);
            } else {
                return 
    true;
            }
        }

        public function 
    prepend($data) {
            return 
    $this->write($data0);
        }

        public function 
    append($data) {
            return 
    $this->write($data$this->size);
        }

        public function 
    truncate($from 0) {
            if (
    $from $this->size) {
                
    $from $this->size;
            }
            
    $this->pointer($from);
            @
    ftruncate($this->fp$from);
            
    $this->reloadFile();
        }

        public function 
    erase($from$to null) {
            if (
    is_null($to)) {
                return 
    $this->truncate($from);
            }
            if (
    is_int($from) && is_int($to)) {
                
    $this->error("Supplied arguments for File::erase() must be ints.");
            }
            
    $tmp_name $this->details['directory']."/".$this->details['filename'].".tmp";
            
    $tmp = new File($tmp_name$this->binary);
            
    $tmp->write($this->read($to));
            
    $this->truncate($from);
            
    $this->write($tmp->read());
            
    $tmp->delete();
        }

        public function 
    close() {
            
    $this->__destruct();
        }

        public function 
    saveAs($dest) {
            
    $tmp = new File($dest$this->binary);
            if (
    is_object($tmp)) {
                
    $tmp->truncate();
                
    $tmp->write($this->read());
                
    $tmp->close();
                return 
    true;
            } else {
                
    $this->alert("File could not be saved to the new location.");
                return 
    false;
            }
        }

        public function 
    copy($dest) {
            if (!@
    copy($this->file$dest)) {
                
    $this->alert("File could not be copied to the new location.");
                return 
    false;
            }
            return 
    true;
        }

        public function 
    delete() {
            
    $this->unlock();
            @
    fclose($this->fp);
            @
    ulink($this->file);
            
    $this->__destruct();
        }

        private function 
    exists() {
            return @
    file_exists($this->file);
        }

        private function 
    lock($operation LOCK_EX) {
            if (!@
    flock($this->fp$operation)) {
                
    $this->kill("File is in use by another source.");
            } else {
                
    $this->locked true;
            }
        }

        private function 
    unlock() {
            if (
    $this->locked) {
                if (@
    flock($this->fpLOCK_UN)) {
                    
    $this->error("File lock could not be released.");
                }
                
    $this->locked false;
            }
        }

        private function 
    pointer($offset null) {
            if (
    is_null($offset)) {
                return 
    ftell($this->fp);
            } else {
                return 
    fseek($this->fp$offset);
            }
        }

        private function 
    reloadFile() {
            
    fclose($this->fp);
            
    $mode "a+";
            if (
    $this->binary) {
                
    $mode .= "b";
            }
            
    $this->fp fopen($this->file$mode);
            
    $this->details(nulltrue);
        }

        private function 
    kill($msg) {
            if (
    $this->debug) {
                echo 
    "From: '".$this->file."' : ".$msg." This instance of File has been terminated.\n";
            }
            
    $this->__destruct();
        }

        private function 
    error($msg) {
            if (
    $this->debug) {
                throw new 
    File_Exception("From: '".$this->file."' : ".$msg);
            }
        }

        private function 
    alert($msg) {
            if (
    $this->debug) {
                echo 
    "Warning From: '".$this->file."' : ".$msg."\n";
            }
        }
    }

    class 
    Open_Files {

        private static 
    $opened = array();

        public function 
    open($file) {
            if (
    in_array($fileself::$opened)) {
                return 
    false;
            }
            
    self::$opened[$file] = true;
            return 
    true;
        }

        public function 
    close($file) {
            if (
    in_array($fileself::$opened)) {
                unset(
    self::$opened[$file]);
            }
        }
    }

    class 
    File_Exception extends RuntimeException {

        public function 
    __construct($message$code 0$values = array()) {
            if (!empty(
    $values)) {
                
    $message vsprintf($message$values);
            }
            
    parent::__construct($message$code);
        }

    - the lid is off the maple syrup again!

  6. #6
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2008
    Posts
    5,757
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    you typo'd unlink()

  7. #7
    That's Right. notepad_coder's Avatar
    Join Date
    Apr 2002
    Location
    Colorado
    Posts
    835
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well, I know it wasn't unlink() causing the problems. But thanks for letting me know I have tried it a few times commenting out the $tmp->delete(); in File::replace
    - the lid is off the maple syrup again!


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •