【问题标题】:How can I store large chunks into json file without memory crash?如何在没有内存崩溃的情况下将大块存储到 json 文件中?
【发布时间】:2020-05-20 05:17:24
【问题描述】:

我有一个数组 $table,它包含 6000 个项目。 当我想将此数组转换为 json 并将其存储到文件中时,我的内存崩溃了。 所以我想到了将数组分成包含 500 个项目的大块:

$table = array_chunk($table, 500);

$table_json = $serializer->serialize($table[0], 'json', $context);

$myfile = fopen($_SERVER['DOCUMENT_ROOT']."/files/myfile.json", "w") or die("Unable to open file!");
file_put_contents($_SERVER['DOCUMENT_ROOT']."/files/myfile.json", $table_json);

现在运行速度很快,但当然现在只存储了 500 个项目。有没有办法添加$table 数组的其他部分而不会导致内存崩溃?

【问题讨论】:

  • 在内存崩溃时向我们展示您的代码。
  • 在 PHP 数组中存储大量数据通常不是一个好主意,然后将其写入 JSON [大文本] 的文件只会让事情变得更糟。您是否有权访问数据库
  • @RiggsFolly 是的,这就是我创建 $table 的方式 $table = $this->em->getRepository('App\\Entity\\Data')->findAll(); 你有什么建议?
  • 那么你为什么要将此数据写入 JSON 格式的文件?
  • 因为我正在使用数据表https://datatables.net/

标签: php json performance memory chunks


【解决方案1】:

你可以做这样的事情你提到你知道如何使用array_chunk(); 让我们来看看使用名为 array_chunk(); 的内置 PHP 函数来简化流程

我们将使用不推荐的 HTML 表格进行设计。使用 CSS 可以更好地完成这项任务,您可以在没有 HTML 和 CSS 的情况下遵循相同的方式。

我们的餐桌:

id  datePosted  firstName   lastName    pictureName          anotherColumn
1   2013-07-01  John        Smith       SmithJohn.jpg        anotherValue
2   2013-05-06  Elroy       Johnson     JohnsonElroy.jpg     anotherValue
3   2013-06-18  Jake        Bible       BibleJake.jpg        anotherValue
4   2013-07-17  Steve       Stevenson   StevensonSteve.jpg   anotherValue
5   2013-04-08  Bill        Smith       SmithBill2.jpg       anotherValue

构建 HTML 表格

PDO 查询用于通过准备好的语句获取数据库信息,注意循环只生成显示列的代码。 检测行开始和结束位置的测试是不必要的。

//INITIALIZE VARIABLES
$colsToDisplay = 3;
$htmlOutput    = array();

//GET PICTURE LIST
$sql = "SELECT datePosted, firstName, lastName, pictureName FROM pictureList ORDER BY datePosted DESC";
$stmt = $pdo->prepare($sql);
$stmt->execute();
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
     $htmlOutput[] = "<td><img src='images/{$row['pictureName']}' alt='' /><br />{$row['firstName']} {$row['lastName']}</td>";
}

循环完成后,包含列信息的数组可以分成三个一组...或分配给$colsToDisplay 的任何值,我们在这里做了什么?我们取了 3表格中的列,因此将表格分为两部分。

while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
     //...
}

//BREAK THE COLUMNS INTO GROUPS
$htmlOutput = array_chunk($htmlOutput, $colsToDisplay);

剩下的就是显示表格信息。请注意,array_chunk() 创建了一个多维数组。 foreach 循环用于处理列组。每个组都分配给$currRow,其中包含当前行的列数组。 implode() 函数用于快速将列显示为字符串。

让我们继续:

//BREAK THE COLUMNS INTO GROUPS
$htmlOutput = array_chunk($htmlOutput, $colsToDisplay);

//DISPLAY TABLE
print '<table>';
foreach($htmlOutput as $currRow) {
     print '<tr>' . implode('', $currRow) . '</tr>';
}
print '</table>';

检查缺失的列标签

您可能已经注意到,添加缺失列的代码被遗漏了。 换句话说,这个例子产生了一个 HTML 表格,其中最后一行只有两列。

显然,根据W3C Markup Validation Service…,缺少的列不需要,因此它们不包括在内。但是,可以通过在调用 array_chunk() 之前运行以下代码来添加它们。

$colsDifference = count($htmlOutput) % $colsToDisplay;
if($colsDifference) {
     while($colsDifference < $colsToDisplay) {           
        $htmlOutput[] = '<td></td>';           
        $colsDifference++;
    } 
} 

最终代码:

    //INITIALIZE VARIABLES
    $colsToDisplay = 3;
    $htmlOutput    = array();


    //GET PICTURE LIST
    $sql = "SELECT datePosted, firstName, lastName, pictureName FROM pictureList ORDER BY datePosted DESC";
    $stmt = $pdo->prepare($sql);
    $stmt->execute();
    while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
         $htmlOutput[] = "<td><img src='images/{$row['pictureName']}' alt='' /><br />{$row['firstName']} {$row['lastName']}</td>";
    }

    //OPTIONAL CODE
    //IF NEEDED, ADD MISSING COLUMNS
    $colsDifference = count($htmlOutput) % $colsToDisplay;
    if($colsDifference) {
         while($colsDifference < $colsToDisplay) {           
            $htmlOutput[] = '<td></td>';           
            $colsDifference++;      
        }
    } 
        //END: OPTIONAL CODE  
        //BREAK THE COLUMNS INTO GROUPS 
   $htmlOutput = array_chunk($htmlOutput, $colsToDisplay);   
        //DISPLAY TABLE print '<table>'; 

    foreach($htmlOutput as $currRow) {      
        print '<tr>' . implode('', $currRow) . '</tr>'; 
    } 
    print '</table>'; 

本教程背后的想法:

  1. 您无需创建文件并将数组写入该文件即可在数据表中显示。
  2. 如果您仍然希望可以(将表格分成两部分)创建两个数组,然后写入文件,然后使用array_push();array_merge(); 将两个数组合二为一。

我可能有不好的解释,请原谅错误,希望这对你的编码生活有帮助:)

【讨论】:

    【解决方案2】:

    坚持您的解决方案,您可以将其他块附加到现有文件中。这适用于setting the flagFILE_APPEND,例如:

    $table_json = $serializer->serialize($table[1], 'json', $context);
    $myfile = fopen($_SERVER['DOCUMENT_ROOT']."/files/myfile.json", "w") or die("Unable to 
    open file!");
    file_put_contents($_SERVER['DOCUMENT_ROOT']."/files/myfile.json", $table_json, FILE_APPEND | LOCK_EX);
    

    LOCK_EX 标志以防止其他人同时写入文件)

    【讨论】:

    • 谢谢,但我的程序怎么知道要附加多少块?你使用循环吗?
    • 是的,因为 $table 是一个数组,你可以使用 for 或 foreach 循环。 php.net/manual/en/control-structures.foreach.php
    • 但是我的内存崩溃了,或者你认为它会比只存储整个数组而不使用块更好吗?
    • 文件追加似乎不起作用,它只是被覆盖
    猜你喜欢
    • 2012-03-19
    • 1970-01-01
    • 1970-01-01
    • 2022-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-30
    • 1970-01-01
    相关资源
    最近更新 更多