fgetcsv读csv最稳妥但需处理编码和指针:用mb_convert_encoding转码、'rb'模式打开、显式指定分隔符、trim清理空格;写入时统一utf-8、加bom、确保字段为字符串;大文件须流式处理;推荐用league\csv库规避兼容性问题。

用 fgetcsv 读取 CSV 文件时,文件指针和编码容易出错
PHP 原生读 CSV 最稳妥的方式是 fgetcsv,但它默认按系统 locale 解析,遇到中文或特殊字符会乱码。必须在打开文件前用 setlocale 或改用 UTF-8 兼容方式处理。
- 先用
mb_convert_encoding把文件内容转成 UTF-8(如果源文件是 GBK/GB2312) - 调用
fopen时加b模式(如'rb'),避免 Windows 下换行符干扰解析 -
fgetcsv第三个参数默认是逗号,若 CSV 用分号或制表符分隔,必须显式传入$delimiter - 每行数据返回为数组,空字段可能变成
null或空字符串,需用array_map('trim', $row)清理首尾空白
用 fputcsv 写入 CSV 时,字段含逗号、换行或引号必须转义
fputcsv 会自动加引号、转义双引号,但前提是字段值是字符串类型。如果传入数字或 null,它不会加引号,导致 Excel 打开错列。
- 确保所有字段都转成字符串:
(string)$value或strval($value) - 写入前手动调用
mb_convert_encoding($row, 'UTF-8', 'auto')统一编码,否则 Excel 可能显示方块 - 写入完毕后记得
fclose($fp),否则文件可能不完整或被锁住 - 如果目标是让 Excel 正确识别 UTF-8,需在文件开头写入 BOM:
fprintf($fp, "\xEF\xBB\xBF")
大文件场景下别一次性 file_get_contents + str_getcsv
str_getcsv 只适合单行解析,误用于整个文件会导致内存爆炸或解析失败——它不识别换行,会把全部内容当一行处理。
- 10MB 以上 CSV 必须流式处理:用
fopen+fgetcsv循环读,每次只存一行数据 - 避免用
file()把整文件读进数组,尤其在低内存环境(如共享主机)会直接报Allowed memory size exhausted - 若需随机访问某几行,先用
SplFileObject的seek()方法跳转,比重读快得多
用 League\Csv 库替代原生函数更省心
原生函数对编码、BOM、特殊分隔符、超长字段的支持太弱,League\Csv 封装了常见坑点,且文档清晰、测试充分。
- 安装:
composer require league/csv - 读取时自动检测 BOM 和编码:
$reader->setInputBOM(true)->setOutputBOM(true) - 支持自定义分隔符、封装符、转义符,且默认兼容 Excel 导出格式
- 写入时可批量插入:
$writer->insertAll($data),内部已处理类型转换和转义
真正麻烦的不是语法,而是不同 Excel 版本对 CSV 的解析差异——比如 Mac Excel 用 \r 换行,Windows 用 \r\n,而 LibreOffice 又认 \n。这些细节原生函数不管,第三方库才兜得住。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











