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

PHP解析CSV文件时如何抛出自定义CsvParserException异常?

解决自定义CsvParserException替换通用Exception的问题

首先,你需要先创建自己的自定义异常类,它必须继承PHP内置的Exception类,这样才能保留异常的核心功能(比如获取错误消息、发生错误的行号等)。

步骤1:定义CsvParserException类

在同一个app命名空间下添加这个类,你可以根据需求扩展它的功能,哪怕是空类也能正常工作,因为已经继承了Exception的所有特性:

<?php

namespace app;

class CsvParserException extends \Exception
{
    // 这里可以添加CSV解析相关的自定义方法/属性,比如错误类型标记
    // 不需要额外功能的话,空类完全够用
}

步骤2:修改CsvParser类的异常抛出逻辑

接下来,把代码中所有抛出\Exception的地方替换成自定义的CsvParserException,同时我帮你优化了验证逻辑——原来的for循环会重复验证同一行的字段多次,现在调整为每一行只验证一次,性能更优:

<?php

namespace app;

class CsvParser{

    public function parse() {
        $row = 1;
        $flag = true;
        
        // 处理文件无法打开的情况,也抛出自定义异常
        if (($handle = fopen("file.csv", "r")) === FALSE) {
            throw new CsvParserException("无法打开文件:file.csv");
        }

        while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
            $num = count($data);
            echo "<p> $num fields in line $row: <br /></p>";
            echo $num;
            $row++;
            
            if($flag) { 
                $flag = false; 
                continue; 
            } // 跳过首行

            // 验证ID字段(第1列,索引0)
            if (!isset($data[0]) || !is_numeric($data[0])) {
                throw new CsvParserException("第{$row}行ID无效:必须是数字类型");
            }

            // 验证第2列(索引1)字符串
            if (!isset($data[1]) || !is_string($data[1])) {
                throw new CsvParserException("第{$row}行第2列无效:必须是字符串类型");
            }

            // 验证第3列(索引2)字符串
            if (!isset($data[2]) || !is_string($data[2])) {
                throw new CsvParserException("第{$row}行第3列无效:必须是字符串类型");
            }

            // 验证日期字段(第4列,索引3)
            $date = strtotime($data[3] ?? '');
            if ($date === false) {
                throw new CsvParserException("第{$row}行第4列日期无效:{$data[3]} 不是合法日期格式");
            }

            // 验证第5列(索引4)的数字列表
            if (!isset($data[4])) {
                throw new CsvParserException("第{$row}行第5列缺失:需要用|分隔的数字列表");
            }
            $splitData = explode('|', $data[4]);
            foreach($splitData as $index => $value) {
                $trimmedValue = trim($value);
                if (!is_numeric($trimmedValue)) {
                    throw new CsvParserException("第{$row}行第5列第{$index}项无效:'{$value}' 不是合法数字");
                }
            }
        }
        fclose($handle);
    }
}

步骤3:捕获并处理自定义异常

当你调用parse方法时,可以精准捕获CSV解析相关的错误,和其他类型的异常区分处理:

<?php

use app\CsvParser;
use app\CsvParserException;

try {
    $parser = new CsvParser();
    $parser->parse();
} catch (CsvParserException $e) {
    echo "CSV解析错误:" . $e->getMessage() . "(错误发生在代码第" . $e->getLine() . "行)";
} catch (\Exception $e) {
    // 处理非CSV解析相关的意外错误
    echo "未知错误:" . $e->getMessage();
}

额外提示

  • 自定义异常继承Exception后,自动拥有getMessage()、getLine()、getFile()等调试方法,能帮你快速定位问题。
  • 我在异常消息里加入了行号、列位置等具体信息,比通用提示更实用,方便你快速找到CSV文件中的损坏数据。

内容的提问来源于stack exchange,提问作者Ebenezer Anand Arapally

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 18:35:28