例如我有一个文件xxxxx.dat(1G大小)这个文件里的数据格式是:111111111111111111111111111111111111111111."\r\n"
222222222222222222222222222222222222222222."\r\n"
......
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."\r\n"
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb."\r\n"
......
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz."\r\n"如果我要从zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz往上读取20条记录,该怎么读取?

解决方案 »

  1.   


    <?php
    $filename = "c:/logfile.log"; //  需要读取的文件
    $sep = "\n"; // 行分隔符
    $count = 5; // 读取行数
    $handle = fopen($filename,"a+");
    $len= strlen($sep);
    $pos = -$len;
    $i = 0;
    $content = ''; // 最终内容
    $cContent = '';// 当前读取内容寄存
    do{
    fseek($handle,$pos,SEEK_END);
    $cContent = fread($handle,$len);
    $content = $cContent.$content;
    $pos -= $len;
    if ($sep === $cContent ){
    $i++;
    }
    }while($i<$count);
    echo $content;
    ?>
      

  2.   


    $a = file("xxx.dat");
    $b = count($a);
    $c = $b-20;
    for($i=$c;$i<$b;$i++)
    {
      echo $a[$i]."<br/>";
    }
      

  3.   

    <?php
    $fp = fopen('test.txt','r');
    $fs = filesize('test.txt');
    $i = $n = NULL;
    while($i<4)
    {
     fseek($fp,$fs--);
     $n = fread($fp,1);
     ($n=="\n")?$i++:1;
     echo $n;
    }
    fclose($fp);
      

  4.   

    参数$i<X即为读多少行.
    一楼的方法在大文件时小心死掉.一次性全部读入内存甚不划算.
      

  5.   

    如果可以用system:
     system("tail -n 20 test.txt");
    如果不可以: 
    3楼的fopen吧
      

  6.   

    <?
    $f = file("xxxxx.dat");
    $count = count($f);
    print_r(array_slice($f,$count-20,$count));
    ?>
      

  7.   

    个人比较倾向6楼的方法,linux系统,并且允许system的话,就用tail把后面的内容取出来好了。
      

  8.   

    殚心竭虑非要使用php系统原配函数;
    或者,没有现成的函数,就走不动了,实在没必要。(而且到底自己写的效率高还是系统自带的效率高,也要测试才知道)支持1楼3楼的自己写的功能函数。只是1楼的没看懂,len的长度好像就是“\n”,好像意思不太对。
      

  9.   

    因为楼数是根据现有回复数来计算。而列表是取每个帖子的缓存列表,然后生成html。而如果前后两个帖子几乎在同一时间发出,有可能后发的帖子先进缓存列表。CSDN开发人员的水平,可想而知。
      

  10.   

    $file_name = 'E:\test.txt';
    $data = file_get_contents($file_name);
    $content = '';  //输出内容
    $line_count = 0;  //行数计算
    $LINE = 20;  //需要截取的行数
    $i = $data_len = strlen($data);
    while ( $i-- > 0 && $line_count < $LINE ) {
    $content = $content.$data{$i};
    if ( $data{$i} == "\n" )
    $line_count++;
    }
    echo strrev($content);
    在E盘放了个120W行的文件测试,效率似乎还不错。
      

  11.   

    搞清楚楼主的文件是整整1G.
    任何用 file或file_get_contents的.你们图代码的方便,就不管内存的死活了?
      

  12.   


    <?php
    function getLatestLines($filename,$count = 20,$sep = "\r\n"){ //  注意这里必须用双引号
        $content = ''; // 最终内容
        $_current = '';// 当前读取内容寄存
        $seper = '';// 分隔符判断
        $seperLen = strlen($sep); // 分隔符长度
        $step= 1; // 每次走多少字符
        $pos = 0;// 起始位置 -1 就是从最后一个开始
        $i = 0;
        $count--;
        $handle = fopen($filename,'a+'); //读写模式,指针会被放在最后  当然也可以探测出 filesize然后从最后往前读。
        while($i < $count && fseek($handle,$pos,SEEK_END) ===0){
            // SEEK_END - 设定位置为文件尾加上 offset 。(要移动到文件尾之前的位置,需要给 offset 传递一个负值。)
            $_current = fread($handle,$step);
            $seper = $_current.$seper;
            if (strlen($seper)>$seperLen){
                $seper = substr($seper, 0, -$seperLen); // 截取当前字符最后几位。与分隔符匹配,所以长度和分隔符要一样。
            }
            $content = $_current.$content;
            $pos -= $step; // 向后退
            if ($sep === $seper ){ // 判断是否是换行或其他分隔符
                $i++;
            }
        }
        fclose($handle);
        return $content;
    }
    $filename = 'c:/logfile.log'; //  需要读取的文件  3.5G 文件已测试过。
    $sep = "\r\n"; // 行分隔符 注意这里必须用双引号-_-#
    $count = 20; // 读取行数 \r\n 读取3行以下有点问题
    echo getLatestLines($filename,$count,$sep);
    ?>
      

  13.   

    /*** 取得文本文件的行数 ***/
    function getlines($filename) {
      $l = 0;
      $fp = fopen($filename, 'r');
      while(fgets($fp)) $l++;
      fclose($fp);
      return $l;
    }/*** 定位到指定行 ***/
    function poslines($filename, $num) {
      $l = 0;
      $fp = fopen($filename, 'r');
      while(fgets($fp)) {
        if($l == $num) break;
        $l++;
      }
      return $fp;
    }/*** 应用 ***/
    $filename = "xxxxx.dat";
    $fp = poslines($filename, getlines($filename) - 20));
    $buf = fgets($fp);
    ...
      

  14.   

    针对大文件操作,file和file_get_contents为误人子弟的方法,切不可提。个人认为3楼为最好的方法,但注意\n为2字符$n = fread($fp,1); //这句应该为$n = fread($fp,2); 
      

  15.   

    “\n为2字符”,实为高论,贫僧受教。
    不过,\n虽为2个字符,但"\n"却是1个字符,请高人明察。
    还有,3楼一个个字符输出,是不可行的。误人子弟的方法,切不可提。另,
    鉴于1G的文件实在太大,贫僧不能亲自测试(即便复制内容时不死机,保存时也怕会死机),因此也懒得编码了。
    有了18楼(贫僧没细看,有点长)和19楼(有点偷懒)的代码,贫僧作为新手就不献丑了。
      

  16.   

    输出只是示意.他自己怎么组装都可以.逐字节读取才能保证安全.长度不确定的情况下,设置步长间距很可能漏读.
    凡是用fgets的地方均不能和fseek配合.fgets是从指针令开始取整行.
    长度未知的话等于白废.你前面提到的多字节问题.我可以直接忽略过.懒得再答此类问题了.