zoukankan      html  css  js  c++  java
  • [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
    "){
            $start=$stream->tell();
        }
        if($ln=="5555555555555
    "){
           $end=$stream->tell();
        }
    }
    var_dump($start,$end);
    
    //直接定位到开始的字节位置
    $stream->seek($start);
    //读取指定字节数的数据
    $res=$stream->read($end - $start);
    
    var_dump($res);

    1.log的内容

    2.获取部分结果

  • 相关阅读:
    Altium Designer如何导出SMT贴片机用的坐标文件
    STM8S003设计注意事项
    Keil4打开KEIL5未响应卡死的问题
    STM32 adc 多通道采集相互串扰问题解决
    STM32 RS485 和串口 只能接收不能发送问题解决
    AD中元器件报警的处理——器件高度报警
    QT乱码解决办法《转》
    STM32下载失败,st-link v2 在线下载sw模式检测不到
    docker部署普罗米修斯监控
    进程管理常用命令
  • 原文地址:https://www.cnblogs.com/taoshihan/p/10913173.html
Copyright © 2011-2022 走看看