【问题标题】:PHP - How to append to a JSON filePHP - 如何附加到 JSON 文件
【发布时间】:2016-10-08 00:34:57
【问题描述】:

我生成 JSON 文件并将其加载到数据表中,这些 JSON 文件可以包含来自我的数据库的数千行。要生成它们,我需要遍历数据库中的每一行并将每个数据库行添加为 JSON 文件中的新行。我遇到的问题是这样的:

致命错误:134217728 字节的允许内存大小已用尽(尝试分配 262643 字节)

我正在做的是我使用 file_get_contents($json_file) 获取 JSON 文件并将其解码为一个数组,然后我将一个新行添加到数组中,然后将数组编码回 JSON 并将其导出到文件file_put_contents($json_file)。

有没有更好的方法来做到这一点?有没有办法可以防止内存随着每次循环迭代而增加?或者有没有办法可以在内存达到限制之前清除它?我需要脚本运行完成,但是由于这个内存问题,它在崩溃之前几乎没有完成 5%。

我可以继续重新运行脚本,每次重新运行它都会向 JSON 文件添加更多行,所以如果这个内存问题是不可避免的,有没有办法自动多次重新运行脚本直到它完成?例如,我可以检测内存使用情况,并检测它何时即将达到限制,然后退出脚本并重新启动它吗?我在 wpengine 上,所以他们不会允许像 exec() 这样的安全风险函数。

【问题讨论】:

  • 嗯,第一个要回答的问题是什么导致内存、数据库、文件大小、数组大小等耗尽。您只使用 128M 就可以相当安全地提高到 512M 左右服务器。但这可能是一个短期的解决方案,具体取决于真正的问题是什么。
  • 问题中不清楚文件是一个大的Json数组,还是一个文件中有多个json数组。我假设是因为file_put_contents?
  • json 的问题是你必须在内存中有完整的对象,如果你可以使用 CSV,你就不会遇到这样的问题,你甚至可以在不读取内容的情况下追加行,但它会仅当您没有嵌套数据并且每一行(标题)都具有相同的架构时才有效。 CSV 文件可以一次读取和写入一行,您可以提高操作系统对文件大小的整数限制。我个人做过超过 1000 万行的文件。如果你不知道它们是什么,它只是一个逗号分隔的列表,带有标题行。

标签: php json memory


【解决方案1】:

所以我改用 CSV 文件,它解决了内存问题。该脚本的运行速度也快得多。 JQuery DataTables 没有内置对 CSV 文件的支持,所以我写了一个函数来将 CSV 文件转换为 JSON:

    public function csv_to_json($post_type) {

        $data = array(
            "recordsTotal"    => $this->num_rows,
            "recordsFiltered" => $this->num_rows,
            "data"=>array()
        );

        if (($handle = fopen($this->csv_file, 'r')) === false) {
            die('Error opening file');
        }

        $headers = fgetcsv($handle, 1024, "\t");
        $complete = array();

        while ($row = fgetcsv($handle, 1024, "\t")) {
            $complete[] = array_combine($headers, $row);
        }

        fclose($handle);

        $data['data'] = $complete;

        file_put_contents($this->json_file,json_encode($data,JSON_PRETTY_PRINT));

    }

所以结果是我创建一个 CSV 文件和一个 JSON 文件比单独创建一个 JSON 文件要快得多,并且内存限制没有问题。

【讨论】:

    【解决方案2】:

    正如我在 cmets 中所说,我个人会使用 CSV 文件。它们有几个优点。

    • 您一次可以读取/写入一行,因此您只需管理一行的内存
    • 您可以将新数据追加到文件中。
    • PHP 有大量使用 fputcsv() 或 SPL 文件对象的内置支持。
    • 您可以使用“Load Data Infile”将它们直接加载到数据库中

    http://dev.mysql.com/doc/refman/5.7/en/load-data.html

    唯一的缺点是

    • 在整个文件中保持相同的架构
    • 没有嵌套的数据结构

    Json 的问题是(据我所知)您必须将整个内容作为单个数据集保存在内存中。因此,您不能像普通文本文件那样流式传输它(逐行)。除了限制 json 数据的大小之外,真的没有解决方案,这可能很容易,也可能不容易做到。您可以增加一些内存,但如果您希望数据继续增长,这只是一个临时解决方案。

    我们在生产环境中使用 CSV 文件,我经常处理 800k 或 1M 行的数据集。我什至见过一个 10M 行的。我们有一个由 CSV 上传填充的 60M 行 (MySql) 表。所以它会工作并且很健壮。

    如果您在 Json 上设置,那么我会想出固定数量的行,并将您的代码设计为一次只运行那么多行。如果没有更多细节,我无法猜测如何做到这一点。

    【讨论】:

    • 我打算使用 CSV 文件,但我担心逗号可能会出现在我的内容中并破坏 CSV 结构。再想一想,我没有充分的理由让逗号出现在那里,所以我要切换到 CSV 文件。
    • 哎呀,我误读了你的观点,我以为你说你可以将 CSV 文件加载到 JQuery 数据表中。我相信这并不难,但使用 JSON 非常简单,您只需通过 AJAX 请求按原样加载 JSON 文件。
    • 哦,我以为你在说数据库。就逗号而言,在 php 中 fputcsv 和 SPL 文件对象句柄自动转义它们不是问题。我唯一遇到的问题是数据\" 反斜杠引号。即便如此,我认为实际输入以 `\` 结尾并且有空格或逗号,PHP 将用空格和逗号用双引号括起来字符串。所以用一个结尾的反斜杠它转义了 php 放入的引号。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-29
    • 2020-09-18
    • 2012-10-11
    • 2011-12-15
    • 2019-12-29
    相关资源
    最近更新 更多