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.

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

报告相同问题?

悬赏问题

  • ¥88 用uniapp写一个多端的程序,用到高德地图,用高德的JSAPI吗?
  • ¥20 关于#c++#的问题:水果店管理系统
  • ¥30 dbLinq最新版linq sqlite
  • ¥20 对D盘进行分盘之前没有将visual studio2022卸载掉,现在该如何下载回来
  • ¥15 完成虚拟机环境配置,还有安装kettle
  • ¥15 2024年全国大学生数据分析大赛A题:直播带货与电商产品的大数据分析 问题5. 请设计一份优惠券的投放策略,需要考虑优惠券的数量、优惠券的金额、投放时间段和投放商品种类等因素。求具体的python代码
  • ¥15 有人会搭建生鲜配送自营+平台的管理系统吗
  • ¥15 用matlab写代码
  • ¥30 motoradmin系统的多对多配置
  • ¥15 求组态王串口自定义通信配置方法或代码?