从JSON获取数据并更新CSV文件的PHP脚本,cpu使用率高

从JSON获取数据并更新CSV文件的PHP脚本,cpu使用率高,php,json,csv,fputcsv,Php,Json,Csv,Fputcsv,我制作了这个PHP脚本,它从JSON文件获取数据,然后编辑或在多个CSV文件的底部添加一行。 使用cronjob,该脚本每60秒运行一次,运行时会占用大量CPU。我不是专家,我可能需要一些技巧来优化它,甚至改变它的工作方式以获得更好的性能。 谢谢你的帮助 //get data from json $coins = 'BTC,ETH,BNB,XRP,USDT,DOT'; $url = 'https://apilink'.$coins; $ch = curl_init($url); curl_set

我制作了这个PHP脚本,它从JSON文件获取数据,然后编辑或在多个CSV文件的底部添加一行。 使用cronjob,该脚本每60秒运行一次,运行时会占用大量CPU。我不是专家,我可能需要一些技巧来优化它,甚至改变它的工作方式以获得更好的性能。 谢谢你的帮助

//get data from json
$coins = 'BTC,ETH,BNB,XRP,USDT,DOT';
$url = 'https://apilink'.$coins;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
$stats = json_decode($result, true);
curl_close($ch);

$timeupd = date('d/m/Y H:i:s');

//FIRST COIN
$date = $stats[0]['price_date'];
$createDate = new DateTime($date);
$date = $createDate->format('Y-m-d');

$cap = $stats[0]['market_cap'];
$high = $stats[0]['high'];
$daypc = number_format((float)$stats[0]['1d']['price_change_pct'] * 100, 2, '.', '');
$weekpc = number_format((float)$stats[0]['7d']['price_change_pct'] * 100, 2, '.', '');
$adjclose = $stats[0]['price'];
$volume = $stats[0]['1d']['volume'];
$monthpc = number_format((float)$stats[0]['30d']['price_change_pct'] * 100, 2, '.', '');
$yearpc = number_format((float)$stats[0]['365d']['price_change_pct'] * 100, 2, '.', '');
$ytdpc = number_format((float)$stats[0]['ytd']['price_change_pct'] * 100, 2, '.', '');

//create array
$array = array($date, $cap, $high, $daypc, $weekpc, $adjclose, $volume, $monthpc, $yearpc, $ytdpc, $timeupd);

//get last row from csv file
$rows = file('/firstcoin.csv');
$last_row = array_pop($rows);
$data = str_getcsv($last_row);

//add new line or modify it
if($date == $data[0] && !empty($stats[0]['price'])){
    $f = '/firstcoin.csv';
    $rows = file($f);
    array_pop($rows);                       // remove final element/row from $array
    file_put_contents($f, implode($rows));  // convert back to string and overwrite file
    $handle = fopen("/firstcoin.csv", "a");
    fputcsv($handle, $array);
    fclose($handle);
} elseif($date != $data[0] && !empty($stats[0]['price'])) {
    $handle = fopen("/firstcoin.csv", "a");
    fputcsv($handle, $array);
    fclose($handle);
} else {
    echo 'EMPTY JSON RESPONSE FOR FIRST COIN';
}

//SECOND COIN
//....other csv

//THIRD COIN
//....other csv

//ETC

您至少要将整个文件读入内存一次,然后在第一种情况下将整个文件写回磁盘。这非常昂贵,而且随着文件的增长,情况会变得更糟。因为您只需要读写文件的末尾,所以应该找到一种方法,只读取最后一行,可以选择删除它,然后将新行写入文件的末尾

这是一个概念证明,您需要仔细测试这种技术,以确保它与系统上的行结束符一起工作

<?php
//get last row from csv file
$handle = fopen('/firstcoin.csv', 'a+');

$data = getLastCsvLine($handle, $lastLineOffset);

//add new line or modify it
if($date == $data[0] && !empty($stats[0]['price'])){
    /*
     * Remove last line from the file
     * getLastCsvLine will set the file pointer to the beginning of the line,
     * so we can just truncate from there then add our line
     */
    ftruncate($handle, $lastLineOffset);
    fputcsv($handle, $array);
} elseif($date != $data[0] && !empty($stats[0]['price'])) {
    fputcsv($handle, $array);
} else {
    echo 'EMPTY JSON RESPONSE FOR FIRST COIN';
}

fclose($handle);

/**
 * Get the last CSV line in a file
 *
 * @param $fileHandle
 * @return array|false
 */
function getLastCsvLine($fileHandle, &$lastLineOffset)
{
    // Set the initial reverse offset
    $cursor = -1;

    // Set the file pointer to the end of the file
    fseek($fileHandle, $cursor, SEEK_END);

    // Rewind past any newlines at the end of the file
    do
    {
        $char = fgetc($fileHandle);
        fseek($fileHandle, --$cursor, SEEK_END);
    } while( $char === "\n" || $char === "\r" );

    // Read backwards until we hit the next newline or the beginning of the file
    do
    {
        // Step backwards one byte
        fseek($fileHandle, --$cursor, SEEK_END);

        // Get the current char
        $char = fgetc($fileHandle);

        // Test to see if it is a newline char
        $foundLineStart = ( $char === false || $char === "\n" || $char === "\r" );
    } while (!$foundLineStart);

    // Set the last line offset var and seek to the offset
    $lastLineOffset = ftell($fileHandle);

    // Return the data for the line
    return fgetcsv($fileHandle);
}

您好,感谢您花时间编写此解决方案。我对此唯一的问题是,无论什么情况,它都会向csv文件添加一个新行(即使第一个if语句为true并且“ftruncate”应该启动并执行其工作),显然getLastCsvLine函数在最后一行的末尾设置指针,因为该文件以一个新的空行结尾(执行“echo ftell()”返回50908,文件长度为50909)尝试更新的示例,它应该可以解决该问题。效果很好,谢谢!