fgetcsv() 无法读取 .xlsx 文件,因其是 zip 压缩的 xml 结构,而 fgetcsv() 仅支持纯文本 csv;必须使用 phpspreadsheet 等支持 office open xml 的库。

为什么直接用 fgetcsv() 读不了 .xlsx 文件
因为 .xlsx 是 ZIP 压缩包格式,里面包含 XML 结构的多张工作表、样式、公式等,fgetcsv() 只能处理纯文本 CSV。强行用它读 .xlsx 会得到乱码或空内容,甚至触发 Warning: fgetcsv() expects parameter 1 to be resource, bool given 这类错误。
必须用支持 Office Open XML 标准的库,PhpSpreadsheet 就是目前最主流的选择(PHPExcel 已停止维护)。
- 安装命令:
composer require phpoffice/phpspreadsheet - 注意 PHP 版本:最低要求
PHP 7.4,若用PHP 8.2+,建议装^2.0版本(^1.25在高版本中可能报Deprecated: Return type of PhpOffice\PhpSpreadsheet\Reader\Xlsx::listWorksheetInfo() - 内存占用明显:一个 10MB 的
.xlsx文件加载后常占 80–120MB 内存,大文件务必用setReadDataOnly(true)
读取 Excel 时如何避免内存溢出和超时
默认全量加载会把整个工作表结构、样式、公式都解析进内存,对 5 万行以上表格非常危险。关键是要“按需加载”。
- 禁用样式和公式:
$reader->setReadDataOnly(true); - 只读指定工作表:
$reader->setLoadSheetsOnly(['Summary']);(传数组,名称必须完全匹配) - 用流式读取(适用于单工作表大数据):
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx(); $reader->setReadDataOnly(true); $spreadsheet = $reader->load('data.xlsx'); $worksheet = $spreadsheet->getActiveSheet(); foreach ($worksheet->getRowIterator() as $row) { ... } - 设置最大执行时间:
set_time_limit(300);(尤其在 CLI 环境下,Web 环境还要调max_execution_time)
getCellByColumnAndRow() 和 getCell() 怎么选
两者都能取单元格值,但参数习惯和边界容错不同,选错容易返回 null 或抛异常。
-
getCellByColumnAndRow(int $column, int $row):列用数字(A=1, B=2),行用数字(从 1 开始)。适合循环遍历,比如for ($col = 1; $col getCellByColumnAndRow($col, $row); } -
getCell(string $coordinate):列用字母('A1','Z100'),更贴近 Excel UI。但拼错坐标(如'A0'或超出范围)会直接 throwPhpOffice\PhpSpreadsheet\Exception - 安全写法:先用
$worksheet->getHighestRow()和$worksheet->getHighestColumn()获取边界,再构造合法坐标
中文乱码、日期变数字、空单元格读成 NULL 怎么办
不是编码问题,而是 PhpSpreadsheet 默认按 Excel 内部类型返回原始值——日期存为序列数,空单元格不参与存储,中文字段本身无乱码风险(UTF-8 是默认)。
- 日期转 PHP 时间:
$dateValue = $cell->getFormattedValue();或手动转换:DateTime::createFromExcel($cell->getValue()); - 空单元格判断:
if ($cell->getValue() === null || $cell->getValue() === '');但注意合并单元格中非主单元格也返回null - 强制转字符串(防数字截断):
(string) $cell->getValue(),尤其对身份证、手机号等长数字字段 - 如果导出 CSV 后中文变问号,检查输出头:
header('Content-Type: text/csv; charset=utf-8');并在 CSV 内容前加\xEF\xBB\xBF(BOM)
真正麻烦的是嵌套公式、跨工作表引用、自定义数字格式——这些场景下 getFormattedValue() 可能失效,得退回到 getValue() + 手动映射格式代码。这类边缘情况没银弹,只能按业务字段逐个适配。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











