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> <?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>