php怎么读取CSV文件_php fgetcsv解析表格数据【导入】

1次阅读

fgetcsv读csv前需手动处理bom、设对编码和文件模式;必须显式指定分隔符、封装符、转义符;勿省略长度参数;空行注释需自行跳过;应流式读取避免内存溢出。

php怎么读取CSV文件_php fgetcsv解析表格数据【导入】

fgetcsv 读 CSV 前必须设对文件指针和编码

php 默认不处理 BOM 和中文编码,直接 fopen + fgetcsv 读 UTF-8 带 BOM 的 CSV,第一行字段名常乱码或错位。这不是 fgetcsvbug,是流底层没跳过 BOM、也没指定输入编码。

  • 打开文件前加 stream_filter_append($fp, 'convert.iconv.UTF-8/UTF-8//IGNORE')(仅 PHP 7.4+ 支持)或手动检测并跳过 BOM 字节
  • 确保文件以 rb 模式打开:fopen('data.csv', 'rb') —— 文本模式(r)在 windows 下可能把 rn 错当 n 截断字段
  • 如果 CSV 来自 excel 或网页导出,大概率含 BOM;用 hexdump -C data.csv | head -n1 看前 3 字节是不是 ef bb bf

fgetcsv 的分隔符、封装符、转义符不是“自动猜”的

很多人以为 fgetcsv 能智能识别不同格式的 CSV,其实它只按你传的参数切——参数不对,数据就裂开。尤其遇到字段里含逗号、换行或双引号时,不显式指定封装符(")和转义符("),fgetcsv 会直接截断或报错。

  • 最安全调用: fgetcsv($fp, 0, ',', '"', '"') —— 第三个参数是分隔符,第四个是封装符,第五个是转义符(PHP 5.3+ 支持第五个参数)
  • Excel 导出的 CSV 通常用双引号封装,且内部双引号写成 "",所以转义符也得设成 ",否则第二层引号会被吃掉
  • 别省略第二个参数(长度限制):设成 0 表示不限长;设太小(如 1024)会导致长字段被截断,且后续行全偏移

空行、注释行、表头跳过要自己控制,fgetcsv 不管这些

fgetcsv 只负责按 CSV 规则解析一行,不会帮你过滤空行、跳过以 # 开头的注释、或识别哪行是 header。实际导入时,这些逻辑漏掉就会导致数据错位或插入失败。

  • 读每行前先 $line = fgets($fp) 判断是否为空或注释:trim($line) === '' || strpos(trim($line), '#') === 0
  • 表头处理建议单独读一次:$header = fgetcsv($fp, 0, ',', '"', '"'),之后循环读数据行,用 array_combine($header, $row) 构建关联数组
  • 注意:如果 CSV 第一行是空行,fgetcsv 返回 false,但文件指针已移动,后续读取会整体下移——务必在 fgetcsv 前检查返回值

内存和大文件:别一次性 file_get_contentsstr_getcsv

有人图省事用 file_get_contents 把整个 CSV 读进内存,再用 str_getcsv 拆——这在几 MB 还行,到 50MB+ 就直接 OOM。而 fgetcsv 是流式读取,只要单行不超内存,整体可处理 GB 级文件。

立即学习PHP免费学习笔记(深入)”;

  • 避免 file('data.csv')file_get_contents + explode("n") —— 这些不识别 CSV 封装规则,遇到换行字段就崩
  • 真要批量导入,建议配合 set_time_limit(0)gc_disable()(处理完再 gc_enable()),防止超时或频繁 GC 拖慢
  • 如果字段含大量 HTML 或 Base64,记得在入库前做 trim()htmlspecialchars_decode(),否则视觉上“空”其实是空白符或实体符

CSV 解析真正难的不是语法,是那些藏在 Excel 保存选项里、http 响应头里、甚至编辑器自动加的不可见字符——它们不会报错,只会让第 372 行的邮箱字段少一个 @ 符号。

text=ZqhQzanResources