<?php
/**
* 设计思路:
* 把文件重新格式化,进行二分查找
* 调取方法:
* $m = new FileSearch("test.log", 200);
* echo $m->search(95500736); //在文件中搜索
* 说明:第一次使用会很慢,因为要生成缓存文件
*/
class FileSearch
{
private $filename; //源文件名
private $maxLength; //源文件中单行的最大长度(按字节算)
private $sorted; //源文件是否已经排好序
private $formatFile; //重新格式化存储的文件名
private $fd;
/**
* 初始化
* @param string $filename 需要检索的文件
* @param int $maxLength 单行的最大长度
* @param int $sorted 源文件是否已经排好序
* @param int $forceReForm 是否强制重新生成索引文件
* @return [type] [description]
*/
public function __construct($filename, $maxLength, $sorted = 1, $forceReForm = 0)
{
$this->filename = $filename;
$this->maxLength = $maxLength;
$this->sorted = $sorted;
$this->formatFile = dirname($this->filename)."/filecache/".md5($this->filename);
if ($forceReForm || !file_exists($this->formatFile)) {
$this->formatFile();
}
}
/**
* 格式化文件
* @return [type] [description]
*/
private function formatFile()
{
if ($this->sorted == 0) {
//对源文件排序
}
//读源文件,写入到新的索引文件
$readfd = fopen($this->filename, 'rb');
$writefd = fopen($this->formatFile.'_tmp', 'wb+');
if ($readfd === false || $writefd === false) {
return false;
}
echo "\n start reformat file $this->filename ..";
while (!feof($readfd)) {
$line = fgets($readfd, 8192);
$id = explode("\t", $line)['0'];
fseek($writefd, ($id - 1) * $this->maxLength);
fwrite($writefd, pack("a".$this->maxLength, $line));
}
echo "\n reformat ok\n";
fclose($readfd);
fclose($writefd);
rename($this->formatFile.'_tmp', $this->formatFile);
}
/**
* 在索引文件中进行二分查找
* @param int $id 进行二分查找的id
* @return [type] [description]
*/
public function search($key)
{
$filesize = filesize($this->formatFile);
$fd = fopen($this->formatFile, "rb");
$left = 0; //行号
$right = ($filesize / $this->maxLength) - 1; //行号
while ($left <= $right) {
$middle = intval(($right + $left)/2);
fseek($fd, ($middle) * $this->maxLength);
$info = unpack("a*", fread($fd, $this->maxLength))['1'];
$lineinfo = explode("\t", $info, 2);
if ($lineinfo['0'] > $key) {
$right = $middle - 1;
} elseif ($lineinfo['0'] < $key) {
$left = $middle + 1;
} else {
fclose($fd);
return $lineinfo['1'];
}
}
fclose($fd);
return false;
}
/**
* 读取固定行数的文本
* @param int $id 行数
* @return [type] [description]
*/
public function getLine($key)
{
$ret = array();
$fd = fopen($this->formatFile, "rb");
if(!is_array($key)) {
$key = array($key);
}
foreach ($key as $v) {
if($v < 100) {
continue;
}
fseek($fd, ($v - 1) * $this->maxLength);
$info = unpack("a*", fread($fd, $this->maxLength))['1'];
$ret[$v] = trim(strstr($info, "\t"));
}
fclose($fd);
return $ret;
}
}
.whl
- 粉丝: 3823
- 资源: 4648
最新资源
- JavaScript的表白代码项目源码.zip
- springboot vue3前后端分离开发入门介绍,分享给有需要的人,仅供参考
- 全国297个地级市城市辖区数据1990-2022年末实有公共汽车出租车数人均城市道路建成区绿地面积供水供气总量医院卫生机构数医生人数GDP第一二三产业增加值分行业从业人员水资源农产品产量利用外资
- Python客流量时间序列预测模型.zip
- 故障预测-灰色预测模型C++源码.zip
- python入门介绍,分享给有需要的人,仅供参考
- c语言入门教程,分享给有需要的人,仅供参考
- yolo入门教程,分享给有需要的人,仅供参考
- 158764节奏盒子Sprunki寄生虫10011000.apk
- 数据压缩领域的哈夫曼树实现与应用
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈