drsb77336 2015-06-23 19:12
浏览 87
已采纳

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

I am trying to write a class that will allow me to write data to a file and then read it. In some cases, I also lock the file for write, then unlock it once the writing is done.

The problem that I am having is when trying to get the content of the file using my getCache() method the file becomes empty. It seems that when the getCache() method is called the content of the file are deleted for some reason.

Here is my class

<?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());

            }

        }
    }   

}

This is how I call my class

<?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();
    }

?>

When commenting the line print_r($cache->getCache('NewKey')); The file 12300000 will have the data below as expected

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;}}}

However, when the method print_r($cache->getCache('NewKey')); is called the file becomes empty.

What am I doing wrong here? Why is my print_r($cache->getCache('NewKey')); method is emptying out the file?

  • 写回答

1条回答 默认 最新

  • dongsi073898 2015-06-23 19:18
    关注
    openFile($mode = "w+")
    

    The documentation for fopen() says:

    'w+' Open for reading and writing; place the file pointer at the beginning of the file and truncate the file to zero length. If the file does not exist, attempt to create it.

    So it resets the file, deleting everything in it.

    Probably you want mode a+:

    'a+' Open for reading and writing; place the file pointer at the end of the file. If the file does not exist, attempt to create it. In this mode, fseek()() only affects the reading position, writes are always appended.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog