[PHP] 使用ftell和fseek函数直接定位文件位置获取部分数据
对于大文件只获取部分数据很有用
1.使用ftell函数可以获取当前指针的字节位置
2.使用fseek函数可以直接定位到指定的位置
3.读取指定字节的数据就可以部分获取文件内容了
<?php class FileStream { private $fp = null; private $mode = 'r'; private $context = null; private $readonly = false; private $writeonly = false; private $appendMode = false; public function __construct($file, $mode = 'r', $context = null) { $mode = trim($mode); if (isset($mode[0])) { $this->mode = strtolower($mode); } if ($context) { $this->context = $context; $this->fp = fopen($file, $mode, false, $this->context); } else { $this->fp = fopen($file, $mode); } if (!$this->fp) { throw new Exception('can not open ' . $file); } if ($this->mode == 'r') { $this->readonly = true; } elseif ($this->mode == 'w') { $this->writeonly = true; } elseif ($this->mode[0] == 'a') { $this->appendMode = true; } } public function __destruct() { $this->close(); } public function close() { if (!$this->fp) { fclose($this->fp); $this->fp = null; } } public function read($size) { if ($this->writeonly) { throw new Exception('write only'); } if (!$this->fp) { throw new Exception('stream already closed'); } $buf = fread($this->fp, $size); if ($buf === false) { throw new Exception('read failed'); } return $buf; } public function readLine() { if ($this->writeonly) { throw new Exception('write only'); } if (!$this->fp) { throw new Exception('stream already closed'); } return fgets($this->fp); } public function readAll() { if ($this->writeonly) { throw new Exception('write only'); } if (!$this->fp) { throw new Exception('stream already closed'); } $buf = ''; while (true) { $s = fread($this->fp, 8192); if ($s === false) { throw new Exception('read failed'); } if (!isset($s[0])) { break; } $buf .= $s; } return $buf; } public function write($data) { if ($this->readonly) { throw new Exception('read only'); } if (!$this->fp) { throw new Exception('stream already closed'); } if (fwrite($this->fp, $data) === false) { throw new Exception('write failed'); } } public function tell() { if ($this->appendMode) { throw new Exception('tell can not work on appendmode'); } if (!$this->fp) { throw new Exception('stream already closed'); } $p = ftell($this->fp); if ($p === false) { throw new Exception('tell failed'); } return $p; } public function seek($position) { if ($this->appendMode) { throw new Exception('seek can not work on seekmode'); } if (!$this->fp) { throw new Exception('stream already closed'); } if (fseek($this->fp, $position) !== 0) { throw new Exception('seek failed'); } } } $stream=new FileStream("1.log"); $start=0; $end=0; //获取开始和结束的字节位置 while($ln=$stream->readLine()){ if($ln=="3333333333333\r\n"){ $start=$stream->tell(); } if($ln=="5555555555555\r\n"){ $end=$stream->tell(); } } var_dump($start,$end); //直接定位到开始的字节位置 $stream->seek($start); //读取指定字节数的数据 $res=$stream->read($end - $start); var_dump($res);
1.log的内容
2.获取部分结果
十年开发经验程序员,离职全心创业中,历时三年开发出的产品《唯一客服系统》
一款基于Golang+Vue开发的在线客服系统,软件著作权编号:2021SR1462600。一套可私有化部署的网站在线客服系统,编译后的二进制文件可直接使用无需搭开发环境,下载zip解压即可,仅依赖MySQL数据库,是一个开箱即用的全渠道在线客服系统,致力于帮助广大开发者/公司快速部署整合私有化客服功能。
开源地址:唯一客服(开源学习版)
官网地址:唯一客服官网