fgetcsv() 是 PHP 中逐行读取 CSV 到数组最稳妥的方式,它自动处理引号、逗号、换行等复杂字段,内存友好且兼容 Excel 导出格式;需配合 fopen/fclose 使用,注意 BOM 头与编码问题。

用 fgetcsv() 逐行读取 CSV 到数组最稳妥
PHP 没有内置“一键 CSV 转数组”函数,fgetcsv() 是标准、可控、内存友好的方式。它按行解析,返回每行的字段数组,适合大小适中的文件(几 MB 内)。别直接用 file_get_contents() + explode(),CSV 里可能含换行、逗号、引号,手动拆分会崩。
实操建议:
- 先用
fopen()打开文件,确保编码是 UTF-8(尤其含中文时,BOM 可能干扰首行) -
fgetcsv()默认以逗号分隔、双引号包裹、反斜杠转义,和 Excel 导出的 CSV 兼容性最好 - 第一行常是表头,可用
fgetcsv()先读一次,再用array_combine()给后续每行打键名 - 记得用
fclose()关闭句柄,否则大文件循环中会耗尽系统资源
$fp = fopen('data.csv', 'r');
if (!$fp) die('无法打开 CSV 文件');
$header = fgetcsv($fp);
$data = [];
while (($row = fgetcsv($fp)) !== false) {
$data[] = array_combine($header, $row);
}
fclose($fp);
遇到中文乱码或 BOM 头怎么办
Windows 下 Excel 保存的 CSV 常带 UTF-8 BOM(\xEF\xBB\xBF),会导致 fgetcsv() 读出的首列键名开头多出乱码,比如 姓名。这不是函数问题,是文件本身带了不可见字节。
解决方法:
立即学习“PHP免费学习笔记(深入)”;
使用 qbo-mileage CLI 及用户凭证,从 Airtable、Outlook 或 Google Calendar 记录生成 QuickBooks Online 里程 CSV 文件。
- 用
file_get_contents()读全文件,用mb_substr()或正则去掉 BOM,再用str_getcsv()解析单行(仅适用于小文件) - 更推荐:打开文件后立即检测并跳过 BOM ——
fseek($fp, 3, SEEK_CUR)(如果前 3 字节是 BOM) - 若数据源固定为 GBK,需用
stream_filter_append($fp, 'convert.iconv.GBK/UTF-8')转码,不能只改mb_internal_encoding()
str_getcsv() 适合单行或小字符串,别硬套大文件
str_getcsv() 是 fgetcsv() 的字符串版,只处理一行文本。有人图省事把整个 CSV 文件用 file_get_contents() 读成大字符串,再 str_getcsv($content) —— 这完全错误:str_getcsv() 不识别换行符,会把整文件当“一列”返回一个超长数组。
正确用法场景:
- 从 POST 表单接收一行 CSV 格式输入(如用户粘贴的“张三,25,上海”)
- 解析 CSV 中某个字段本身又是逗号分隔的子数据(需二次调用)
- 配合
explode("\n", $content)后逐行处理,但要注意空行、\r\n 和 \n 混用问题
大文件(>10MB)必须流式处理,避免内存溢出
用 file() 或 file_get_contents() 把整个 CSV 加载进内存,10MB 文件就可能吃掉 30MB+ PHP 内存,超限直接 500。生产环境务必流式读取。
关键点:
- 坚持用
fopen()+fgetcsv()循环,每轮只保留一行数据在内存 - 如果要过滤或转换数据,边读边处理,别全存进
$data数组再操作 - 写入数据库时,用批量插入(如
INSERT INTO ... VALUES (...), (...)),别每行INSERT一次 - 临时文件可考虑用
tmpfile(),比sys_get_temp_dir()更安全


















