当前位置: 首页> 最新文章列表> 用fgetcsv读取CSV文件时乱码怎么办?详解编码问题的处理技巧

用fgetcsv读取CSV文件时乱码怎么办?详解编码问题的处理技巧

gitbox 2025-06-08

一、为什么使用 fgetcsv 会出现乱码?

fgetcsv() 是 PHP 提供的一个方便的函数,用于按行读取 CSV 文件,并将每一行的数据以数组形式返回。但是,它,也不会自动进行转码。如果你尝试读取一个以 GBKBIG5 编码保存的文件,而你的 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 是通过浏览器上传的怎么办?

如果用户上传的 CSV 文件可能来自不同的操作系统(Windows、Mac、Linux),也可能是不同软件(Excel、WPS)保存的,此时字符编码更加不可控。建议在上传后先将编码统一处理,然后再用 fgetcsv() 读取。

可以考虑将上传的 CSV 文件保存为临时文件,并使用上述自动检测+转码的方式进行统一处理:

<code> <?php

if (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>