You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP文件入库脚本异常排查:非法字符/行数错误致任务阻塞

气象数据入库脚本阻塞问题排查与修复

核心问题点分析

1. 文件资源操作错误

修改后的代码里$fileToString = file_get_contents($file);完全错误——file_get_contents()接收的是文件路径字符串,不是fopen()返回的文件资源句柄。这会导致$fileToString获取失败,后续合法性判断全错,同时打乱文件指针位置,造成读取异常。

2. 异常文件未释放资源

当文件不符合合法性条件时(else if分支不执行),代码未调用fclose($file)释放文件资源。未关闭的句柄会被系统占用,轻则导致后续文件无法打开,重则造成进程阻塞。

3. 文件合法性判断逻辑漏洞

  • 行数值判断不准确:正常文件有9行数据,对应8个换行符,但如果文件最后一行无换行(如异常示例2),substr_count($fileToString, "\n") == 8会误判为合法;而有空行的异常文件(示例1)换行符数量超标,直接被跳过但未清空文件,导致下次循环重复处理该异常文件,陷入死循环阻塞后续流程。
  • 非法字符检测正则错误:原正则/^£$%&*()}{@#~?><>,|=_+¬¤ÇÓü]/中的^是行首锚定符,仅会匹配字符串开头的非法字符,根本检测不到字符串中间的非法内容(如示例1里的0.0¤)。正确写法应去掉^,改为检测整个字符串是否包含目标字符的字符集正则。
  • 空行判断逻辑无效:fgets($file) != ""读取第一行后移动了文件指针,虽然后续用rewind()移回,但如果第一行是空的就直接跳过,不符合“检查文件是否为空”的实际需求。

4. 异常文件未清理

不符合条件的文件未执行清空操作,导致脚本每次循环都会重复处理同一个异常文件,永远无法进入后续文件的处理流程,这是阻塞的直接原因。

修复后的代码示例

foreach ($listWeathStatV2 as $weathStat) {
    $filePath = __DIR__ . "/data/DB_" . $weathStat . ".txt";
    $file = fopen($filePath, "r") or die("无法打开文件: " . $filePath);
    $fileContent = fread($file, filesize($filePath));
    fclose($file); // 提前关闭资源,避免占用

    $isValid = true;
    // 检查文件是否为空
    if (trim($fileContent) === "") {
        $isValid = false;
    }
    // 检查非法字符(修正正则,转义特殊字符)
    elseif (preg_match('/[£\$%&*()}{@#~?><>,|=_+¬¤ÇÓü]/', $fileContent)) {
        $isValid = false;
    }
    // 检查行数(按换行分割后计数,兼容最后一行无换行的情况)
    $lines = preg_split('/\r?\n/', trim($fileContent));
    if (count($lines) !== 9) {
        $isValid = false;
    }

    if ($isValid) {
        // 重新打开文件读取数据
        $file = fopen($filePath, "r") or die("无法打开文件: " . $filePath);
        $heure = trim(fgets($file));
        $temp = trim(fgets($file));
        $humidity = trim(fgets($file));
        $pressure = trim(fgets($file));
        $pluvio = trim(fgets($file));
        $anemo = trim(fgets($file));
        $gir = trim(fgets($file));
        $lumino = trim(fgets($file));
        $battLvl = trim(fgets($file));
        fclose($file);

        // 使用预编译语句防止SQL注入
        $query = "INSERT INTO " . $weathStat . " (heure, valTemp, valHumid, valPressure, valPluvio, valAnemo, valGir, valLumino, battLevel) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
        $stmt = mysqli_prepare($connect, $query);
        mysqli_stmt_bind_param($stmt, "sdddddddd", $heure, $temp, $humidity, $pressure, $pluvio, $anemo, $gir, $lumino, $battLvl);
        mysqli_stmt_execute($stmt) or die("SQL执行错误: " . mysqli_error($connect));
        mysqli_stmt_close($stmt);
    }

    // 无论文件是否合法,都清空文件,避免重复处理
    file_put_contents($filePath, "");
}

额外优化说明

  • 提前拼接文件路径,避免重复计算;
  • 先读取内容并关闭资源,减少系统资源占用;
  • 用trim()处理每行数据,去除换行符和多余空格;
  • 改用MySQLi预编译语句,彻底规避SQL注入风险;
  • 统一清空文件,确保不会重复处理同一文件,阻塞后续流程。

内容的提问来源于stack exchange,提问作者Laurent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 16:27:05