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

  • 相关阅读:
    kotlin异常类
    kotlin之null值安全性
    kotlin之操作符重载
    kotlin 之相等判断
    Java 的抽象特性:抽象类与接口深度解析
    人人都能够做深度学习应用:入门篇
    HBase源代码分析之HRegionServer上MemStore的flush处理流程(一)
    通讯录结构体方法的实现 和VS中存在的一些问题的分析
    2015爱奇艺暑期实习生面试
    cocos2d-x 源代码分析 : EventDispatcher、EventListener、Event 源代码分析 (新触摸机制,新的NotificationCenter机制)
  • 原文地址:https://www.cnblogs.com/taoshihan/p/10913173.html
Copyright © 2011-2022 走看看