fgetcsv() 是 PHP 提供的一个方便的函数,用于按行读取 CSV 文件,并将每一行的数据以数组形式返回。但是,它,也不会自动进行转码。如果你尝试读取一个以 GBK 或 BIG5 编码保存的文件,而你的 PHP 环境或网页输出是 UTF-8,那么输出的内容就会出现乱码。
为了解决乱码问题,我们需要在读取每一行数据后,将其从原始编码转为目标编码(通常是 UTF-8)。这通常通过 PHP 的 mb_convert_encoding() 或 iconv() 函数来实现。
假设我们有一个 GBK 编码的 CSV 文件,我们想将其内容正确显示为 UTF-8,可以使用以下代码:
<code> <?php$filename = "data.csv"; // 假设 CSV 文件是 GBK 编码
$handle = fopen($filename, "r");
if ($handle !== false) {
while (($data = fgetcsv($handle)) !== false) {
// 将每一列都从 GBK 转为 UTF-8
foreach ($data as &$field) {
$field = mb_convert_encoding($field, "UTF-8", "GBK");
}
unset($field); // 避免引用问题
print_r($data); // 输出转码后的内容
}
fclose($handle);
} else {
echo "无法打开文件: $filename";
}
?>
</code>
如果你不确定文件的原始编码是什么,可以使用 mb_detect_encoding() 来自动检测:
<code> <?php$filename = "data.csv";
$handle = fopen($filename, "r");
if ($handle !== false) {
$firstLine = fgets($handle);
rewind($handle); // 读完第一行后指针回到文件开头
$encoding = mb_detect_encoding($firstLine, ["GBK", "UTF-8", "BIG5", "SJIS"], true);
if (!$encoding) {
$encoding = "GBK"; // 如果无法检测,默认用 GBK
}
while (($data = fgetcsv($handle)) !== false) {
foreach ($data as &$field) {
$field = mb_convert_encoding($field, "UTF-8", $encoding);
}
unset($field);
print_r($data);
}
fclose($handle);
} else {
echo "文件无法打开";
}
?>
</code>
如果用户上传的 CSV 文件可能来自不同的操作系统(Windows、Mac、Linux),也可能是不同软件(Excel、WPS)保存的,此时字符编码更加不可控。建议在上传后先将编码统一处理,然后再用 fgetcsv() 读取。
可以考虑将上传的 CSV 文件保存为临时文件,并使用上述自动检测+转码的方式进行统一处理:
<code> <?phpif (isset($_FILES['csvfile']) && $_FILES['csvfile']['error'] === UPLOAD_ERR_OK) {
$tmpFile = $_FILES['csvfile']['tmp_name'];
$handle = fopen($tmpFile, "r");
if ($handle !== false) {
$firstLine = fgets($handle);
rewind($handle);
$encoding = mb_detect_encoding($firstLine, ["GBK", "UTF-8", "BIG5", "SJIS"], true);
if (!$encoding) {
$encoding = "GBK";
}
while (($data = fgetcsv($handle)) !== false) {
foreach ($data as &$field) {
$field = mb_convert_encoding($field, "UTF-8", $encoding);
}
unset($field);
print_r($data);
}
fclose($handle);
} else {
echo "无法读取上传的文件";
}
} else {
echo "上传失败或文件无效";
}
?>
</code>