如何使用PHP和Ajax实时读取文件

时间:2016-01-23 18:08:44

标签: javascript php jquery ajax

我想实时读取一个txt文件并更新我前端添加的新行。文本文件包含两个用户的日志数据。我已经尝试了一些方法来找到工作方式,但是作为js的PHP脚本都不能按我的意愿工作。

JS脚本

<?php 

    session_start();

    // get the requirements for the file name
    $MyEmail = $_SESSION['login'];
    $FriendEmail = $_POST['friend'];

    if (strcmp($MyEmail, $FriendEmail) < 0) {
        $FileName = $MyEmail.'-'.$FriendEmail.'.txt';
    }
    else {
        $FileName = $FriendEmail.'-'.$MyEmail.'.txt';
    }


    $File = fopen('data/'.$FileName, "r") or die(json_encode(array_push($messages, "Error")));

    // count the lines exist in the file
    $count = 0;
    while(!feof($File)){
        $tmp = fgets($File);
        $count++;
    }

    // if the session var that holds the offset position is not set 
    // or has value more than the lines of text file
    if (!isset($_SESSION['pos']) || $_SESSION['pos'] >= $count) {
       $_SESSION['pos'] = 0; // back to the beginning
    } 

    // the array that holds the logs data
    $messages = array(); 

    // move the pointer to the current position
    fseek($File, $_SESSION['pos']);

    // read the file
    while(!feof($File)){
        $msg = fgets($File);
        $msg1 = explode("<!@#@>", $msg);
        array_push($messages, $msg1);
        $_SESSION['pos']++;
    }

    // get the current offset position
    //$_SESSION['pos'] = ftell($File);

    // return the array
    echo json_encode($messages);

    fclose($File)
?>

GetMesssage.php

GetNewMesssages()

Explainig

假设我们在调用ShowNewMessages()函数时第一次启动例程。该函数将触发php并从文件中获取数据。

接下来如果数据持有somenthing,返回数组不为空,我们执行GetNewMesssages()函数并更新前端。

当我们完成后,我们开始另一个ftell()回调。

我想要什么

我想每隔N秒检查一次新添加的行,并更新我的前端。

问题

我在php和js脚本中都存在问题。我不想添加两个问题。

在PHP中

我没有找到如何使用GetNewMessages()来获取新添加的行。由于脚本的工作原理是这样,所以每次更新时我都会将所有文件放入我的数组中。

在JS中

在JS中,我遇到了同步ajax调用的问题。这意味着在setTimeout()函数的每次调用中,我再次获得2-3次函数调用。它与line_id <BreakString> some data <BreakString> blah blah another_line_id <BreakString> some_other data <BreakString> blah blah 2 有关,但我也无法找到如何设置回叫。

更新

我从中读取的文本文件示例:

connection.query('SELECT count(id) as wynik FROM used where asset_id = 
  \''+asid+'\'', inventory[i],function(err,wiersze){
    console.log(inventory[i]);
});

注意:没有任何意义。它只是将内容分离到数组。

更新2

在主持人发出通知后,我的问题很小,只是为了找到实时读取文件的最佳方法,保留我的结构。

1 个答案:

答案 0 :(得分:1)

PHP

在PHP中fseek()将文件指针设置为文件中的特定字节偏移量。您似乎在代码中做出的假设是fseek()会将指针设置为文件中的特定行。

假设您的消息不包含任何换行符(此代码中没有这样的真相),您可以使用file()代替将整个文件加载到PHP中的数组中并确定你需要的行偏移量。

例如......

$file = file($fileName);
$mssages = array_slice($file, $_SESSION['pos']);

这将为您提供从$_SESSION['pos']行偏移开始的文件中所有行的数组。

重构现有的PHP代码

要重构您现有的代码,您可以修改以下循环,以便在它到达$_SESSION['pos']时停止阅读,从而继续从此点开始加载新消息的逻辑...

$count = 0;
while(!feof($File)){
    $tmp = fgets($File);
    $count++;
}

相反,你这样做......

$count = 0;
while(!feof($File) || $count < $_SESSION['pos']){
    $tmp = fgets($File);
    $count++;
}

现在删除fseek($File, $_SESSION['pos'])部分,你的第二个循环应该在你期望的行上找到。

文件格式

如果存储这些消息的文件是一种行分隔格式,则文件中的每一行只代表一条消息(这似乎是您在代码中做出的假设)那么避免消息内容本身破坏文件的最安全的方法是以不允许消息有效负载中的换行字符的方式对消息内容进行编码。此类编码的示例包括 JSON Base64

后者将为您提供大约33%的虚增存储成本,但两者对于行分隔文件格式都是安全的。

的Javascript

目前还不清楚为什么您的javascript逻辑使用currend来确定它是否应该使用setTimeout()。如果您希望全局循环每10秒不断检查一次新数据,则应该从全局范围调用setInterval(GetNewMesssages, 10000)一次,而不是有条件地使用setTimeout()。在您的代码中,如果当前消息是最后一条消息的条件,您将不再从js再次调用PHP以检查新消息,这显然不是您想要的。 setTimeoutsetInterval之间的区别在于setTimeout仅在达到计时器时触发一次,而setInterval持续< / strong>以给定的间隔触发回调。