PHP读取含日文内容CSV文件时乱码、字符匹配失败问题
问题根因
乱码的核心原因是编码判断和配置全错:
- 你的CSV文件实际编码是
EUC-JP(日文环境常用传统编码),根本不是ISO-8859-1。你看到的°ú¤¹þ¤à就是典型的EUC-JP字节流被当成ISO-8859-1(拉丁1)解析的乱码特征 - 之前用iconv转换损坏数据,是因为错误指定源编码为ISO-8859-1,转码的输入编码从根上就不对
- 你把HTTP响应头、页面meta标签的字符集全设成ISO-8859-1,相当于拿西文字符集解析日文编码字节,不仅显示乱码,字符串比对时因为两边字节序列完全不匹配,等值判断永远返回false
- 代码里加的
setlocale(LC_ALL, 'ja_JP.EUC-JP')只影响本地化相关函数(比如时间格式、排序规则),不会自动给文件内容做转码,加了没有任何作用。
解决方案
全链路统一使用UTF-8作为处理和输出编码,不要依赖系统自动编码识别:
- 读取CSV拿到原始字节后,显式将内容从EUC-JP转为UTF-8再做后续处理
- 把页面所有编码声明(HTTP头、meta标签)统一改成UTF-8
- 做字符串比对时,确保参与对比的两个字符串都是UTF-8编码
修正后的可运行代码如下:
<?php // 声明页面输出为UTF-8编码 header("Content-Type: text/html; charset=UTF-8"); ?> <!DOCTYPE html> <html lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>日文CSV读取测试</title> </head> <body> <?php $row = 1; // 待匹配的目标字符串,文件本身保存为UTF-8即可 $targetStr = "引き込む"; if (($handle = fopen("/srv/http/Japanese/testFile.csv", "r")) !== FALSE) { while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) { $row++; for ($i = 0; $i < 4; ++$i) { // 核心转码逻辑:将读取到的EUC-JP内容转为UTF-8 // 加//IGNORE参数用于跳过少量无法识别的异常字节,避免转码直接中断 $data[$i] = iconv("EUC-JP", "UTF-8//IGNORE", $data[$i]); echo $data[$i] . "<br />"; // 转码完成后字符串等值判断可正常生效 if ($data[$i] === $targetStr) { echo "*匹配到目标字段:引き込む*<br />"; } } echo "<br />"; if ($row > 1000) break; } fclose($handle); } else { echo print_r(error_get_last(), true); } ?> </body> </html>
补充注意事项
- 如果按上面代码运行后仍有个别字符乱码,可以先打印首行内容的实际编码:
echo mb_detect_encoding($data[0], 'EUC-JP, SJIS, UTF-8, ISO-2022-JP');,部分老日文CSV会使用Shift_JIS编码,将iconv的源编码参数替换为SJIS即可 - 所有编码处理链路不要混用字符集:文件读取转码、内部逻辑处理、页面输出全链路统一用UTF-8,可以避免绝大多数日文、中文多字节字符乱码问题
- 你原来的等值判断代码有语法错误:
if ($data[$i]) == "引き込む")多写了一个右括号,修正语法后配合转码逻辑即可正常匹配。
内容的提问来源于stack exchange,提问作者Liyara
相关产品推荐
相关产品推荐

