當前位置: 首頁> 最新文章列表> 用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>