代码语言
.
CSharp
.
JS
Java
Asp.Net
C
MSSQL
PHP
Css
PLSQL
Python
Shell
EBS
ASP
Perl
ObjC
VB.Net
VBS
MYSQL
GO
Delphi
AS
DB2
Domino
Rails
ActionScript
Scala
代码分类
文件
系统
字符串
数据库
网络相关
图形/GUI
多媒体
算法
游戏
Jquery
Extjs
Android
HTML5
菜单
网页交互
WinForm
控件
企业应用
安全与加密
脚本/批处理
开放平台
其它
【
PHP
】
PHP高效文本缓存类
作者:
天哲
/ 发布于
2014/10/10
/
545
一个key对应一行记录, 首先读取首行的配置文件, 得到key对应的行数, 然后取之.写入时同样会计算key对应的行数, 有则更新, 无则增加.fopen + flock控制并发.
<?php $old = sprintf('%1.4f', memory_get_peak_usage() / 1024) .' KB'; class caches{ public $keep_time = 3600; public $file_path = './cache.txt'; private $handle = null; private $time = 0; public function __construct(){ $this->time = time(); } public function read($key, $keep_time=0){ # 取得第一行. 判断过期, 不存在, 异常情况, 影响返回值即可. 返回值决定write方法的调用. $keep_time === 0 && $keep_time = $this->keep_time; $list = $this->__get_one(); # 是否更新判断. $check = true; if(!$list[$key]) $check = false; if($check && (time() - $list[$key]['t']) >= $keep_time) $check = false; # 取得第几行数据. $line = $list[$key]['l']+0; $i = 1; $data = ''; if($this->handle){ while(!feof($this->handle)){ if($i === $line){ $data = fgets($this->handle); }else{ // TODO: 有没有好办法跳过这步... fgets($this->handle); } $i ++; } } # 无论如何都保障数据为数组返回. if($data){ $data = $this->__data_parse($data,'DECODE'); } !$data && $data = array(); return $data; } public function write($key, $val){ # 取得第一行. 判断key是否已经存在了.. $list = $this->__get_one(); # 什么情况下可以写入. if($list[$key]){ # 已经过期的情况下. write函数被调用后, 不管如何都当作过期. $list[$key]['t'] = $this->time; $list['end'] = $list[$key]['l']; }else{ $list[$key] = array('t'=>$this->time,'l'=>($list['end']+1)); $list['end'] = $list[$key]['l']; } # 数据加密处理后再传给__write. $list['end'] 表示更新哪一行. return $this->__write($list['end'], $this->__data_parse($val), serialize($list)); } private function __get_one(){ $this->__read_fopens(); if(!$this->handle) return array(); $list = array(); if($seria = rtrim(fgets($this->handle))){ $list = unserialize($seria); unset($seria); } !$list && $list = array(); return $list; } private function __data_parse($data, $cls='ENCODE'){ # $State 参数以减少is_string, count两函数的调用. if($cls === 'ENCODE'){ # 一定要返回无换行的一行. 切记 # gzcompress 非常占内存, 只是写入时执行. $data = base64_encode(gzcompress(serialize($data),9)); }else{ $data = unserialize(gzuncompress(base64_decode(rtrim($data)))); if($State === false && count($data) === 1 && isset($data[0]) === true){ $data = $data[0]; } } return $data; } private function __write($line, $data, $firstline){ $savedata = array(); $line +=0; $i = 1; $savedata[0] = $firstline; if($this->handle){ while(!feof($this->handle)){ $savedata[$i] = rtrim(fgets($this->handle)); if($i === $line){ $savedata[$i]= $data; } $i ++; } } if(!$savedata[$line]) $savedata[$line] = $data; if($this->handle) $this->__closes(); # 重新写入文件. if(!$fp = fopen($this->file_path, 'wb')) if(!$fp = fopen($this->file_path, 'wb')) if(!$fp = fopen($this->file_path, 'wb')) if(!$fp = fopen($this->file_path, 'wb')) if(!$fp = fopen($this->file_path, 'wb')) return 0; flock($fp, LOCK_EX | LOCK_NB); $ints = 0; //$ints = fwrite($fp, implode(PHP_EOL, $savedata)); foreach($savedata AS $key => $val){ if($key === 0){ $ints += fwrite($fp,$val); }else{ $ints += fwrite($fp,PHP_EOL.$val); } if($key === 0 && $ints <= 0) break; } unset($savedata); flock($fp, LOCK_UN); fclose($fp); return $ints; } private function __read_fopens(){ $cls = 'rb'; if($this->handle) $this->__closes(); if(is_file($this->file_path) === false) return false; if(!$this->handle = fopen($this->file_path,$cls)) if(!$this->handle = fopen($this->file_path,$cls)) if(!$this->handle = fopen($this->file_path,$cls)) if(!$this->handle = fopen($this->file_path,$cls)) if(!$this->handle = fopen($this->file_path,$cls)) $this->handle = null; if($this->handle) flock($this->handle,LOCK_EX | LOCK_NB); } private function __closes(){ if($this->handle){ flock($this->handle, LOCK_UN); fclose($this->handle); $this->handle = null; } } } ########################################### 调用代码 ######################################### set_time_limit(0); $atime = microtime(true); $obj = new caches(); $read = 1; // (0 / 1) 写入或者读, 测试效果. $size = 10000; // 10K $arr = range(1,100); // 首次要快得多, 200:1秒, 1000:11秒 foreach($arr AS $val){ if($read == 0){ // 写入测试. $ints = $obj->write('key'.$val,array('key'=>str_repeat('A',$size))); echo 'key'.$val.' write size: '. ($ints / 1000).' KB'; }else{ // 读缓存测试. $ints = $obj->read('key'.$val); echo 'key'.$val.' read size: '. strlen($ints['key']) / 1000 .' KB'; } } #################################### 以下代码为监控作用 #################################### echo '执行时间: '; echo sprintf('%1.4f',microtime(true) - $atime).' 秒'; echo '<hr>内存监控: '; echo $new = sprintf('%1.4f', memory_get_peak_usage() / 1024) .' KB'; echo '<hr>原始内存: '; echo $old; echo '<hr>增加内存: '; echo sprintf('%1.4f',$new - $old) .' KB'; exit(); ?>
试试其它关键字
缓存类
同语言下
.
用net匹配并替换iOS标准的emoji表情符号
.
处理带Emoji表情的的字符串
.
获取微信昵称时 过滤特殊字符
.
通过判断上传文件的头字符来判断文件的类型
.
模拟百度URL加密解密算法
.
以太坊检查地址是否合法
.
实现crontab解析类
.
获取每个月的开始和结束时间
.
图片上传工具类
.
APP手机应用信息采集
可能有用的
.
C#实现的html内容截取
.
List 切割成几份 工具类
.
SQL查询 多列合并成一行用逗号隔开
.
一行一行读取txt的内容
.
C#动态修改文件夹名称(FSO实现,不移动文件)
.
c# 移动文件或文件夹
.
c#图片添加水印
.
Java PDF转换成图片并输出给前台展示
.
网站后台修改图片尺寸代码
.
处理大图片在缩略图时的展示
天哲
贡献的其它代码
(
13
)
.
JAVA 驼峰与下划线的属性名互相转换
.
获取远程文件HTML
.
判断字符串是否为数值型字符串
.
获取星期一,获取第几周
.
aspx与ascx值传递与设置
.
把同一字段里的多行数据用一行显示
.
固定页脚
.
使用委派代替继承
.
禁用右键单击上下文菜单
.
Jquery- ID与Class之间转换
Copyright © 2004 - 2024 dezai.cn. All Rights Reserved
站长博客
粤ICP备13059550号-3