PHP 读取大文件尾部20行

baofeng0113 2009-01-17 04:21:25
例如我有一个文件xxxxx.dat(1G大小)

这个文件里的数据格式是:

111111111111111111111111111111111111111111."\r\n"
222222222222222222222222222222222222222222."\r\n"
......
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."\r\n"
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb."\r\n"
......
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz."\r\n"

如果我要从

zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz往上读取20条记录,该怎么读取?
...全文
924 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
baofen14787 2010-04-22
  • 打赏
  • 举报
回复
如果读取指定的分段怎么修改啊?
Dogfish 2009-01-20
  • 打赏
  • 举报
回复
每行有长度限制吗?如果有,倒读一定量的数据,再从后面拿20行。
SysTem128 2009-01-19
  • 打赏
  • 举报
回复

<?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);
?>

SysTem128 2009-01-19
  • 打赏
  • 举报
回复
版主的形象……全毁了-_-#
xuzuning 2009-01-19
  • 打赏
  • 举报
回复
/*** 取得文本文件的行数 ***/
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);
...
frj000 2009-01-19
  • 打赏
  • 举报
回复
up~
syu 2009-01-19
  • 打赏
  • 举报
回复
输出只是示意.他自己怎么组装都可以.

逐字节读取才能保证安全.长度不确定的情况下,设置步长间距很可能漏读.
凡是用fgets的地方均不能和fseek配合.fgets是从指针令开始取整行.
长度未知的话等于白废.

你前面提到的多字节问题.我可以直接忽略过.懒得再答此类问题了.
wjdlt_1997 2009-01-19
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 yiwusuo 的回复:]
针对大文件操作,file和file_get_contents为误人子弟的方法,切不可提。

个人认为3楼为最好的方法,但注意\n为2字符

$n = fread($fp,1); //这句应该为$n = fread($fp,2);
[/Quote]
“\n为2字符”,实为高论,贫僧受教。
不过,\n虽为2个字符,但"\n"却是1个字符,请高人明察。
还有,3楼一个个字符输出,是不可行的。误人子弟的方法,切不可提。

另,
鉴于1G的文件实在太大,贫僧不能亲自测试(即便复制内容时不死机,保存时也怕会死机),因此也懒得编码了。
有了18楼(贫僧没细看,有点长)和19楼(有点偷懒)的代码,贫僧作为新手就不献丑了。
yiwusuo 2009-01-19
  • 打赏
  • 举报
回复
针对大文件操作,file和file_get_contents为误人子弟的方法,切不可提。

个人认为3楼为最好的方法,但注意\n为2字符

$n = fread($fp,1); //这句应该为$n = fread($fp,2);
dubiousway 2009-01-18
  • 打赏
  • 举报
回复
这个贴子真奇怪哈,

楼主下面为什么是2楼?
2楼为什么在1楼上面???!!!
dubiousway 2009-01-18
  • 打赏
  • 举报
回复
殚心竭虑非要使用php系统原配函数;
或者,没有现成的函数,就走不动了,实在没必要。(而且到底自己写的效率高还是系统自带的效率高,也要测试才知道)

支持1楼3楼的自己写的功能函数。只是1楼的没看懂,len的长度好像就是“\n”,好像意思不太对。
wjdlt_1997 2009-01-18
  • 打赏
  • 举报
回复
3楼你的代码在遇到多字节字符时会出现乱码的,不能那样输出。
wjdlt_1997 2009-01-18
  • 打赏
  • 举报
回复
我想问个问题:啥情况会出现一个文件有1G这么巨大?比如……
wjdlt_1997 2009-01-18
  • 打赏
  • 举报
回复
我错了,没看到1G……
syu 2009-01-18
  • 打赏
  • 举报
回复
搞清楚楼主的文件是整整1G.
任何用 file或file_get_contents的.你们图代码的方便,就不管内存的死活了?
wjdlt_1997 2009-01-18
  • 打赏
  • 举报
回复
$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行的文件测试,效率似乎还不错。
baofeng0113 2009-01-18
  • 打赏
  • 举报
回复
我也是一楼没太看懂,方便的话一楼的牛来来解释一下吧
surfchen 2009-01-18
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 dubiousway 的回复:]
这个贴子真奇怪哈,

楼主下面为什么是2楼?
2楼为什么在1楼上面???!!!
[/Quote]
因为楼数是根据现有回复数来计算。

而列表是取每个帖子的缓存列表,然后生成html。而如果前后两个帖子几乎在同一时间发出,有可能后发的帖子先进缓存列表。

CSDN开发人员的水平,可想而知。
bookmoth 2009-01-17
  • 打赏
  • 举报
回复
个人比较倾向6楼的方法,linux系统,并且允许system的话,就用tail把后面的内容取出来好了。
xiongbing529 2009-01-17
  • 打赏
  • 举报
回复


<?
$f = file("xxxxx.dat");
$count = count($f);
print_r(array_slice($f,$count-20,$count));
?>
加载更多回复(6)

21,886

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧