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.获取部分结果

  • 相关阅读:
    jquery 拼图小游戏
    重要参考SQL
    SQL Server save transaction
    SelectList类的构造函数
    一步步教你整合SSM框架(Spring MVC+Spring+MyBatis)详细教程重要
    springMVC,spring和Hibernate整合(重要)
    delphi环境变量
    C# Chart 点击获取当前点击坐标和Series
    如何修改 app.config 的配置信息
    C#中使用设置(Settings.settings) Properties.Settings.Default .(配置文件相当重要)
  • 原文地址:https://www.cnblogs.com/taoshihan/p/10913173.html
Copyright © 2011-2022 走看看