在PHP中从末尾开始读取CSV文件

3
我正在使用PHP从CSV文件中提取车辆GPS数据。这些数据至少每30秒捕获一次,涵盖了70多个车辆的19列数据。这将产生数千行数据和大约614kb的文件大小。新数据附加到文件末尾。我需要为每个车辆提取最后一行数据,这应该代表最近的状态。我可以为每个单元格提取出一行数据,但由于CSV文件按时间顺序排列,我提取的是文件中最旧的数据而不是最新的数据。有可能从后往前读取CSV吗?我见过一些解决方案,但它们通常涉及将整个文件加载到内存中,然后反转它,这听起来非常低效。我还有其他选择吗?谢谢您提供的任何建议。
编辑:我正在使用这些数据实时地在地图上标记位置。这些数据仅以CSV格式提供给我,因此我认为导入数据库不可行。

也许CSV不适合在这种情况下保存数据。为什么不使用数据库呢? - Ibu
只需要几分钟就可以将您的数据导出到数据库中,我建议使用MySQL。 - Ibu
@lbu:他/她可能正在多个系统之间使用共享文件。如果是这样,我建议改用 Web 服务。 - Nabeel
2个回答

5
使用 fseek 函数,您可以将指针设置到文件末尾并将其偏移为负以倒序读取文件。

这难道不需要我将整个文件加载到内存中吗? - garnertb
1
不,你需要使用 fopen 打开资源流,使用 fseek 设置指针,并使用各种 fget* 函数来读取所需的数据量(这是加载到内存中的数据量)。 - cem
1
请考虑在您的回答中添加更多细节,以涵盖问题标题。 - Peyman Mohamadpour
问题在于你将在用户空间中解析文件,这会很慢。理想情况下,你可以使用 fseek 设置流指针,然后指示 fgetcsv 反向读取行。由于 OP 只需要最后一行,所以在这种情况下可以工作,但通常从 PHP 中反向读取 CSV 文件似乎会受到重大性能损失。 - quickshiftin

0
如果您必须使用CSV文件而非数据库,那么或许可以逐行读取文件。这样可以避免存储超过最后一行的数据在内存中(感谢垃圾回收器)。
$handle = @fopen("/path/to/yourfile.csv", "r");
if ($handle) {
    while (($line = fgets($handle)) !== false) {
        // old values of $last are garbage collected after re-assignment
        $last = $line;
        // you can perform optional computations on past data here if desired
    }
    if (!feof($handle)) {
        echo "Error: unexpected fgets() fail\n";
    }
    fclose($handle);

    // $last will now contain the last line of the file.
    // You may now do whatever with it
}

更新:我没有看到 fseek() 的帖子。如果你只需要最后一行,那就是正确的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接