【问题标题】:Blocking file-read in php?在php中阻止文件读取?
【发布时间】:2009-08-11 18:50:19
【问题描述】:

我想从文本文件中读取所有内容并回显它。但是在我阅读时可能会有更多行写入文本文件,所以我不希望脚本在到达文件末尾时退出,而是我不希望它永远等待更多行。这在php中可以吗?

【问题讨论】:

  • 这取决于您的目标功能类型。此脚本是否在来自浏览器的请求的上下文中执行?是可以无限运行的 CLI 脚本吗?
  • 这是一个 PHP 脚本,将从命令行运行还是从 Web 服务器运行?
  • 命令行脚本有什么关系?

标签: php input io filehandle


【解决方案1】:

这只是一个猜测,但请尝试通过(passthru)“tail -f”输出。

但您需要找到一种方法来刷新()您的缓冲区。


恕我直言,一个更好的解决方案是构建一个 ajax 站点。

将文件的内容读入一个数组。存储会话中的行数。打印文件的内容。

每隔 x 秒向检查文件的脚本发起一次 ajax 请求,如果行数大于会话数,则将结果附加到页面。


你可以使用 popen() inststed:

$f = popen("tail -f /where/ever/your/file/is 2>&1", 'r');
while(!feof($f)) {
    $buffer = fgets($f);
    echo "$buffer\n";
    flush();
    sleep(1);
}
pclose($f)

睡眠很重要,没有它你将拥有 100% 的 CPU 时间。

【讨论】:

  • 实际上我用tail做了一个可行的解决方案,但它使用了一个消耗所有cpu的无限循环,这就是我想要某种“阻塞”调用的原因。每 X 秒调用一次是不够的,我需要实时,而且它不是网站,所以没有 ajax。
  • tail -f 是“实时的”,根本不需要循环或 php。
  • 那个 popen-solution 几乎和我的一模一样。问题是睡眠,它使延迟太大。
  • 然后尝试 usleep() 并尽可能低,但我猜你越低,你的 CPU 负载就越重。
  • 我现在尝试了完全不休眠,它仍然很慢,可能是它执行来自php的tail命令太慢了。
【解决方案2】:

事实上,当你“回显”它时,它会进入缓冲区。因此,如果在浏览器仍在接收输出时添加了新内容,您想要的是“附加”新内容。这是不可能的(但有一些方法可以解决这个问题)。

【讨论】:

  • 你知道有flush()吗?
【解决方案3】:

我解决了。

诀窍是使用 fopen 并在到达 eof 时将光标移动到上一个位置并从那里继续阅读。

<?php
$handle = fopen('text.txt', 'r');
$lastpos = 0;
while(true){
   if (!feof($handle)){
       echo fread($handle,8192);
       flush();
       $lastpos = ftell($handle);
   }else{
       fseek($handle,$lastpos);
   }
}
?>

不过还是很耗cpu,不知道怎么解决。

【讨论】:

  • 你在忙循环,当然它会消耗所有 CPU。尝试在fseek 行之后添加usleep(50000)。这将休眠 50 毫秒,这将大大降低您的 CPU 使用率,而不会显着影响您的延迟。为了做得更好,您需要使用 inotify(假设您使用的系统支持它)。
  • 是的,我知道这是因为循环,usleep 有效,但我并不是真正的睡眠解决方案的粉丝。虽然 inotify 似乎正是我一直在寻找的东西,但我明天会调查。
【解决方案4】:

您也可以使用filemtime:您将获得最新的修改时间戳,发送输出,最后再次将存储的filemtime 与当前的进行比较。

无论如何,如果您希望脚本与浏览器(或客户端)同时运行,您应该使用块(freadflush)发送输出,然后检查最后的任何更改。如果有变化,重新打开文件,从最新位置读取(可以得到while(!feof())循环外的位置)。

【讨论】:

    猜你喜欢
    • 2016-10-08
    • 1970-01-01
    • 2017-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-19
    相关资源
    最近更新 更多