加BOM能解决乱码是因为Excel依赖文件开头的EF BB BF字节标识识别UTF-8编码,否则按系统默认GBK解析导致中文乱码;PHP中须在任何输出前用echo "\xEF\xBB\xBF"写入BOM。

PHP导出CSV时出现中文乱码,最常见原因是文件缺少UTF-8 BOM头,导致Excel等软件误判编码为ANSI(如GBK),从而显示乱码。加BOM是简单有效的解决方案。
为什么加BOM能解决乱码?
Excel在打开CSV文件时,不会读取HTTP头或meta声明,而是依赖文件开头的字节标记来识别编码。UTF-8 BOM(EF BB BF)是一组不可见的三字节标识,明确告诉Excel:“这是UTF-8编码”。没有它,Excel常按系统默认编码(如Windows简体中文为GBK)解析,导致中文变成问号或方块。
Miller (mlr) 是一个命令行工具,用于查询、整形和重新格式化名称索引数据,如 CSV、TSV、JSON 和 JSON Lines。它将 awk、sed、cut、join 和 sort 的功能整合到一个专为结构化数据处理而构建的单一工具中。
PHP中正确添加UTF-8 BOM
必须在输出任何内容(包括空格、换行、echo、header之前)写入BOM。推荐写法:
- 使用 echo "\xEF\xBB\xBF"; —— 最直接,兼容所有PHP版本
- 避免用 file_put_contents($file, "\xEF\xBB\xBF" . $content),除非你确认$content本身不含BOM,否则可能重复写入
- 若用fputcsv,需先fwrite($fp, "\xEF\xBB\xBF"),再fputcsv,且确保文件以wb模式打开(二进制写入,防止Windows下自动换行干扰)
其他关键注意事项
- 不要用mb_convert_encoding转BOM:BOM不是字符,不能靠编码转换生成;手动写入字节即可
- Header设置要匹配:Content-Type保持 text/csv;charset=utf-8 可加可不加,Excel不认这个,但浏览器下载时更规范
- 检查源数据编码:确保数据库查询/变量本身是UTF-8(如PDO设置 charset=utf8mb4,MySQLi用 set_charset('utf8mb4'))
- 避免输出缓冲干扰:导出前调用 ob_end_clean(),清除可能存在的前置输出(如Warning、空格)
一个最小可用示例
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="data.csv"');
echo "\xEF\xBB\xBF"; // 关键:BOM必须第一行、无空格、无换行
$fp = fopen('php://output', 'w');
fputcsv($fp, ['姓名', '城市', '备注']);
fputcsv($fp, ['张三', '上海', '测试用户']);
fclose($fp);


















