PHP将UTF-8转UTF-16LE导出CSV时ndash字符转换失败如何处理
适配Office 365的CSV导出ndash字符乱码修复方案
问题根因
- 未添加UTF-16LE专属的字节顺序标记(BOM),Office 365打开CSV时会误判编码,导致特殊字符显示异常
- 原代码提前将单个字段转换为UTF-16LE再调用
fputcsv,该函数原生仅支持单字节字符处理,插入分隔符、转义符时会破坏多字节编码的结构,是ndash乱码的核心诱因 iconv的//TRANSLIT参数依赖系统locale配置,部分环境下无法正确转写ndash(Unicode编码U+2013)这类特殊符号
修复代码
直接替换原有业务逻辑即可:
$data = $eventHelper->getProgramForCsvExport($event); $response = new StreamedResponse(); $filename = 'program-' . $event->getShortName() . $event->getShortYear() . '.csv'; $response->setCallback(function () use ($data) { $output = fopen('php://output', 'w+'); // 写入UTF-16LE BOM,让Office正确识别编码 fwrite($output, "\xFF\xFE"); foreach ($data as $row) { // 先生成UTF-8格式的单行CSV内容 $temp = fopen('php://temp', 'w+'); fputcsv($temp, $row, ';'); rewind($temp); $utf8Line = fread($temp, 1048576); fclose($temp); // 整行统一转换为UTF-16LE,无需转写/忽略参数 $utf16Line = iconv('UTF-8', 'UTF-16LE', $utf8Line); fwrite($output, $utf16Line); } fclose($output); }); $response->headers->set('Content-Type', 'text/csv; charset=utf-16le'); $response->headers->set('Content-Disposition', 'attachment; filename="' . $filename . '"'); return $response;
可选优化
如果仍有极个别特殊字符无法正常显示,可以在转码前对字符串做简单替换,比如将ndash直接替换为普通短横线:
$utf8Line = str_replace('–', '-', $utf8Line);
该方案不需要使用HTML实体,不会影响CSV的正常读取。
内容的提问来源于stack exchange,提问作者bibamann
相关产品推荐
相关产品推荐

