从PHP fseek()/ rewind()写入JSON文件不起作用

时间:2014-04-19 18:32:26

标签: php json

我正在开发一个记录器类,正在添加的JSON具有以下格式

{"log_owner" : "test123","log_message" : "Has logged in","log_timestamp" : "1397921556","log_type" : "1"}

要检索它,我需要围绕所有不同JSON对象的方括号,如下所示:

[
    {"log_owner" : "test456","log_message" : "Has logged in","log_timestamp" : "1397921856","log_type" : "2"}
    {"log_owner" : "test123","log_message" : "Has logged in","log_timestamp" : "1397921556","log_type" : "1"}
]

每当文件不存在时,我就设法将它插入文件的开头,但主要问题在于在我添加新对象时将结束括号移动到文件的末尾,我试图将我的文件指针移到之前的2个位置,以便能够覆盖最后一个括号,继续为每个新条目添加结束括号,我试图通过以下方式完成此操作:

if(!$content_new) {
$pos=ftell($handle);
fseek($handle,$pos-2);
}
fwrite($handle, $content);
fclose($handle);

似乎它不适用于.json个文件,因为我无法将我的文件指针移动到任何其他行或倒回它。

我怎么能做到这一点?任何形式的改进指导或建议都受到高度赞赏。

谢谢。

1 个答案:

答案 0 :(得分:1)

直接解决您的问题 - 快速而肮脏。

<?php
function writeLog($path, $newLine) 
{
    $exists = file_exists($path);
    $handle = fopen($path, 'c');
    if (!$exists) {
        // first write to log file
        $line = "[" . PHP_EOL . $newLine . PHP_EOL . "]";
    } else {
        // file exists so it has one or more logged lines
        $line = "," . PHP_EOL . $newLine . PHP_EOL . "]";
        fseek($handle , -(strlen(PHP_EOL) + 1) , SEEK_END);
    }
    fwrite($handle, $line);
    fclose($handle);
}
$path = __DIR__ . '/file.json';
// delete file if exists - for tests
if (file_exists($path)) {
    unlink($path);
}
$line = '{"log_owner" : "test123","log_message" : "Has logged in","log_timestamp" : "1397921556","log_type" : "1"}';
for ($i = 0; $i < 10; $i++) {
    writeLog($path, $line);
}

问题

  1. 并发
  2. 缩放
  3. JSON不易编辑和查看
  4. 不容易过滤
  5. 使用CSV,输出JSON

    <?php
    function writeLogCSV($path, $newLine) 
    {
        $handle = fopen($path, 'a');
        fputcsv($handle, $newLine);
        fclose($handle);
    }
    
    function readLogCsv ($path) 
    {
        $handle = fopen($path, 'r');
        $rows = [];
        while (false !== ($line = fgetcsv($handle))) {
            $rows[] = array_combine(
                ["log_owner", "log_message", "log_timestamp", "log_type"],
                $line
            );
        }
        fclose($handle);
        echo json_encode($rows);
    }
    $path = __DIR__ . '/file.csv';
    // delete file if exists - for tests
    if (file_exists($path)) {
        unlink($path);
    }
    $line = ["test123", "Has logged in", "1397921556", "1"];
    for ($i = 0; $i < 10; $i++) {
        writeLogCSV($path, $line);
    }
    readLogCsv($path);
    

    好的部分:

    1. 易于阅读和书写
    2. 问题:

      1. 缩放
      2. 并发
      3. 不容易过滤
      4. 将您的日志存储在数据库中或使用日志服务,输出JSON

        好的部分

        1. 没有并发问题
        2. 轻松过滤
        3. 速度
        4. 适合缩放