对于大文件只获取部分数据很有用
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.获取部分结果