尝试使用PHP读取文件时为什么我的文件总是空的?

时间:2015-06-23 19:12:21

标签: php fopen fread flock fclose

我正在尝试编写一个允许我将数据写入文件然后读取它的类。在某些情况下,我还会锁定文件以进行写入,然后在写入完成后将其解锁。

我遇到的问题是,当我尝试使用getCache()方法获取文件内容时,该文件变为空。似乎在调用getCache()方法时,由于某种原因删除了文件的内容。

这是我的班级

<?php

namespace ICWS;

use \ICWS\showVar;
use \DirectoryIterator;
/**
 * CacheHandler
 *
 * @package ICWS
 */
class CacheHandler {

    /* Max time second allowed to keep a session File */
    private $maxTimeAllowed = 300;


    private $filename = '';
    private $handle;

    public function __construct( $filename ){

        $this->filename = $filename;

        // 5% chance to collect garbage when the class is initialized.
        if(rand(1, 100) <= 5){
            $this->collectGarbage();
        }
    }


    /**
    * Add/Update the cached array in the session
    *
    * @param string $key
    * @param bigint $id
    * @param array $field
    * @return void
    */  
    public function updateCache($key, $id, array $field)
    {

        $currentVal = (object) $field;
        $this->openFile();

        $this->lockFile();
        $storage = $this->readFile();
        //create a new if the $id does not exists in the cache
        if( isset($storage[$key]) && array_key_exists($id, $storage[$key]) ){

            $currentVal = (object) $storage[$key][$id];

            foreach($field as $k => $v){
                $currentVal->$k = $v; //update existing key or add a new one
            }

        }

        $storage[$key][$id] =  $currentVal; 
        new showVar($storage);
        $this->updateFile($storage);
        $this->unlockFile();

        $this->closeFile();
    }

    /**
    * gets the current cache/session for a giving $key
    *
    * @param string $key
    * @return object or boolean
    */  
    public function getCache($key)
    {
        $value = false;
        $this->openFile();

        $storage = $this->readFile();

        if(isset($storage[$key])){
            $value = $storage[$key];
        }

        $this->closeFile();

        return $value;
    }

    /**
    * removes the $id from the cache/session
    *
    * @param string $key
    * @param bigint $id
    * @return boolean
    */      
    public function removeCache($key, $id)
    {

        $this->openFile();

        $this->lockFile();
        $storage = $this->readFile();

        if( !isset($storage[$key][$id])){
            $this->unlockFile();
            $this->closeFile();
            return false;
        }

        unset($storage[$key][$id]);
        $this->updateFile($storage);
        $this->unlockFile();
        $this->closeFile();
        return true;
    }



    /**
    * unset a session
    *
    * @param argument $keys
    * @return void
    */  
    public function truncateCache()
    {
        if(file_exists($this->filename)){
            unlink($this->filename);
        }
    }

    /**
    * Open a file in a giving mode
    *
    * @params string $mode 
    * @return void
    */
    private function openFile( $mode = "w+"){
        $this->handle = fopen($this->filename, $mode);

        if(!$this->handle){
            throw new exception('The File could not be opened!');
        }
    }

    /**
    * Close the file
    * @return void
    */
    private function closeFile(){

        fclose($this->handle);
        $this->handle = null;
    }

    /**
    * Update the file with array data
    * @param array $data the array in that has the data
    * @return void
    */
    private function updateFile(array $data = array() ){
        $raw = serialize($data);    
        fwrite($this->handle, $raw);
    }

    /**
    * Read the data from the opned file
    *
    * @params string $mode 
    * @return array of the data found in the file
    */
    private function readFile() {

        $length = filesize($this->filename);
        if($length > 0){
             rewind($this->handle);
            $raw = fread($this->handle, filesize($this->filename));
            return unserialize($raw);
        }

        return array();
    }


    /**
    * Lock the file
    *
    * @return void
    */  
    private function lockFile( $maxAttempts = 100, $lockType = LOCK_EX) {

        $i = 0;
        while($i <= $maxAttempts){

            // acquire an exclusive lock
            if( flock($this->handle, LOCK_EX) ){
                break;
            }

            ++$i;
        }
    }


    /**
    * Unlock the file
    *
    * @return void
    */  
    private function unlockFile() {

        fflush($this->handle);
        flock($this->handle, LOCK_UN);
    }

    /**
    * Remove add cache files
    *
    * @return void
    */  
    private function collectGarbage(){
        $mydir = dirname($this->filename);

        $dir = new DirectoryIterator( $mydir );
        $time = strtotime("now");
        foreach ($dir as $file) {

            if (  !$file->isDot()
                && $file->isFile()
                && ($time - $file->getATime()) > $this->maxTimeAllowed
                && isset($file->getFilename) && $file->getFilename != 'index.html'
            ) {
                unlink($file->getPathName());

            }

        }
    }   

}

这就是我打电话给我的课程

<?php
    require 'autoloader.php';

    try {
        $cache = new \ICWS\CacheHandler('cache/12300000');

        $field = array('name' => 'Mike A', 'Address' => '123 S Main', 'phone' => '2152456245', 'ext' => 123);
        $cache->updateCache('NewKey', '123456', $field);

        echo '<pre>';
        print_r($cache->getCache('NewKey'));
        echo '</pre>';
    } catch (exception $e){

        echo $e->getMessage();
    }

?>

评论专栏print_r($cache->getCache('NewKey'));时,文件12300000将按预期显示以下数据

a:1:{s:6:"NewKey";a:1:{i:123456;O:8:"stdClass":4:{s:4:"name";s:6:"Mike A";s:7:"Address";s:10:"123 S Main";s:5:"phone";s:10:"2152456245";s:3:"ext";i:123;}}}

但是,当调用方法print_r($cache->getCache('NewKey'));时,文件变为空。

我在这里做错了什么?为什么我的print_r($cache->getCache('NewKey'));方法会清空文件?

1 个答案:

答案 0 :(得分:3)

openFile($mode = "w+")

documentation for fopen()说:

  

'w +'开放阅读和写作;将文件指针放在文件的开头,并将文件截断为零长度。如果该文件不存在,请尝试创建它。

因此它会重置文件,删除其中的所有内容。

您可能想要模式a+

  

'a +'开放阅读和写作;将文件指针放在文件的末尾。如果该文件不存在,请尝试创建它。在此模式下,fseek()()仅影响读取位置,始终追加写入。