PHP读取包含英日混合字符的CSV文件出现乱码如何解决?
核心原因
你遇到的乱码本质是CSV文件的存储编码和PHP输出的编码不匹配,直接echo硬编码的日文可以正常显示,说明PHP本身的输出编码配置是正常的,问题只出在CSV读取后的编码转换环节。
解决步骤
- 第一步:确认CSV实际编码
用本地文本编辑器(如VS Code、Notepad++)打开CSV文件,右下角即可查看文件的实际编码,日文CSV常见编码为Shift-JIS、EUC-JP,也有可能是带BOM的UTF-8,不要默认假设为无BOM的UTF-8。 - 第二步:读取后显式转码再输出
不要直接输出file_get_contents读取的原始内容,需根据CSV的实际编码转成你需要的输出编码(一般为UTF-8),示例代码:
如果不确定原编码,可以传入多个候选编码让函数自动匹配:// 读取CSV原始内容 $raw_csv = file_get_contents('your_target.csv'); // 假设CSV原编码为Shift-JIS,转成UTF-8输出 $utf8_csv = mb_convert_encoding($raw_csv, 'UTF-8', 'SJIS'); // 显式指定响应编码,避免浏览器识别错误 header('Content-Type: text/plain; charset=utf-8'); echo $utf8_csv;$utf8_csv = mb_convert_encoding($raw_csv, 'UTF-8', ['SJIS', 'EUC-JP', 'UTF-8']); - 第三步:如果需要解析CSV内容做后续处理,优先用内置
fgetcsv函数,避免自行拆分字符串出错,示例代码:// 适配日文编码的区域设置,避免fgetcsv拆分异常 setlocale(LC_ALL, 'ja_JP.SJIS'); $handle = fopen('your_target.csv', 'r'); header('Content-Type: text/html; charset=utf-8'); while (($row = fgetcsv($handle)) !== FALSE) { // 仅对第二列转码也可,全列转码也没问题 $row[1] = mb_convert_encoding($row[1], 'UTF-8', 'SJIS'); // 自定义处理逻辑 echo "第一列:{$row[0]},第二列:{$row[1]}<br>"; } fclose($handle); - 特殊情况处理:如果CSV是带BOM的UTF-8编码,需要先移除BOM头再处理:
$raw_csv = file_get_contents('your_target.csv'); // 判断是否存在UTF-8 BOM头,存在则移除 if (substr($raw_csv, 0, 3) == pack('CCC', 0xef, 0xbb, 0xbf)) { $raw_csv = substr($raw_csv, 3); }
注意事项
- 所有输出页面必须显式声明
header指定编码,即使PHP配置中默认编码为UTF-8,显式声明可以避免浏览器自动识别编码出错。 mb_convert_encoding的第三个参数必须和CSV实际编码匹配,否则转码仍然会出现乱码。
内容的提问来源于stack exchange,提问作者Oklas Mathew
相关产品推荐
相关产品推荐

