分解文件中的一行会在 PHP 中出现未定义的偏移错误

Exploding a line from a file gives Undefined Offset error in PHP

我正在尝试逐行读取文件 ($txtFile)。然后将行 ($line) 中的不同项目存储在一个数组 ($pieces) 中,以逗号分隔。代码如下。

 <?php
    include_once __DIR__.'/connect.php';

    function createURL($ticker)
    {
        $currentPeriod = time(); 
        return "https://query1.finance.yahoo.com/v7/finance/download/$ticker?period1=1538917807&period2=1541596207&interval=1d&events=history&crumb=6DH0b71wPwr";
    }

    function getCSVFile($url, $outputFile)
    {
        $content = file_get_contents($url);
        $content = str_replace("Date,Open,High,Low,Close,Adj Close,Volume", "", $content);
        $content = trim($content);
        file_put_contents($outputFile, $content);
    }

    function fileToDatabase($txtFile, $tableName)
    {
        $file = fopen($txtFile, "r");
        while (!feof($file)) {
            $line = fgets($file);
            $pieces = explode(",", $line);
            print_r($pieces);
            $date = $pieces[0];
            $open = $pieces[1];
            $high = $pieces[2];
            $low = $pieces[3];
            $close = $pieces[4];
            $adj_close = $pieces[5];
            $volume = $pieces[6];
            $amount_change = $adj_close-$open;
            $percent_change = ($amount_change/$open)*100;
            $sql = "SELECT * FROM $tableName";
            $result = $conn->query($sql);

            if (!$result) {
                $createQuery = "CREATE TABLE $tableName (
                    date TIMESTAMP PRIMARY KEY,
                    open FLOAT,
                    high FLOAT,
                    low FLOAT,
                    close FLOAT,
                    adj_close FLOAT,
                    volume INT,
                    amount_change FLOAT,
                    percent_change FLOAT
                )";
                $conn->query($createQuery);
            }

            $insertQuery = "INSERT INTO $tableName VALUES (
                '$date', '$open', '$high', '$low', '$close', '$adj_close', '$volume', '$amount_change', '$percent_change'
            )";
            $conn->query($insertQuery);
        }
        fclose($file);
    }

function main()
{
    $pathToTickerFile = __DIR__."/tickerMaster.txt";
    $mainTickerFile = fopen($pathToTickerFile, "r");
    while (!feof($mainTickerFile)) {
        $companyTicker = fgets($mainTickerFile);
        $companyTicker = trim($companyTicker);

        $fileURL = createURL($companyTicker);
        $companyTxtFile = __DIR__."/txtFiles/".$companyTicker.".txt";
        getCSVFile($fileURL, $companyTxtFile);
        fileToDatabase($companyTxtFile, $companyTicker);
    }
    fclose($mainTickerFile);
    echo "The stocks have been downloaded!";
}

main();

?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Stock Downloader</title>
</head>
<body>
</body>
</html>

但我收到以下错误:

PHP Notice:  Undefined offset: 1
PHP Notice:  Undefined offset: 2
PHP Notice:  Undefined offset: 3
PHP Notice:  Undefined offset: 4
PHP Notice:  Undefined offset: 5
PHP Notice:  Undefined offset: 6

我正在使用 PHP-7.0 并且我无法理解这段代码有什么问题。我该如何摆脱这个错误?

您的文件包含空行(或可能多行)。您通常会在文件的最后看到它。

因此,explode() returns 具有单个空值的数组,而您期望的是 7(键 0 到 6)。

在将行分解为数组之前,请检查它是否确实为空。或者在创建数组后对其进行计数,并验证是否存在预期的键数。

在对数组进行索引之前,您可能会检查 $pieces 中的项目数,例如计算爆炸的项目数 returns:

$file = fopen($txtFile, "r");
while (!feof($file)) {
    $line = fgets($file);
    $pieces = explode(",", $line);
    if (count($pieces) > 6) {
        $date = $pieces[0];
        $open = $pieces[1];
        $high = $pieces[2];
        $low = $pieces[3];
        $close = $pieces[4];
        $adj_close = $pieces[5];
        $volume = $pieces[6];
    }
}

一个快速修复方法是检查一行是否包含 7 个元素,因此在展开后,只需检查数组有多少个元素,如果没有足够的值,则跳过其余处理。 ..

$pieces = explode(",", $line);
if ( count($pieces) != 7)   {
    continue;
}
$date = $pieces[0];
// ....

您还应该考虑使用准备好的语句来提供更高的安全性,尽管您仍然需要像现在一样替换 table 名称(您不能使用 table 名称作为绑定变量)。

还有一个建议,在执行 INSERT 操作时,始终列出列名...

INSERT INTO $tableName (date, open, ... )
   VALUES ('$date', '$open', ...)

因为这确保清楚哪一列在哪里,如果进行了任何 table 更改,则 INSERT 明确说明了它对哪些列使用了哪些值。