使用 fgetcsv() 讀取 CSV 時,中文欄位比對失敗,strlen() 長度不符,實際上是編碼不一致 (CSV 為 Big5/GBK,PHP 內部為 UTF-8)。
mb_detect_encoding($str, 'UTF-8, BIG5, GBK, CP950')mb_convert_encoding($str, 'UTF-8', $detected)<?php
$fp = fopen('data.csv', 'r');
if (!$fp) die("無法開啟檔案");
// 讀取標題列
$header = fgetcsv($fp);
$header = array_map(function($h) {
return sanitize_csv_field($h);
}, $header);
while (($row = fgetcsv($fp)) !== false) {
$row = array_map('sanitize_csv_field', $row);
$data = array_combine($header, $row);
// 現在可以正常比對中文
if ($data['狀態'] === '已出貨') {
// 處理邏輯...
}
}
fclose($fp);
function sanitize_csv_field($field) {
if ($field === null || $field === '') return '';
$enc = mb_detect_encoding($field, 'UTF-8, BIG5, GBK, CP950, ASCII', true);
if ($enc && $enc !== 'UTF-8') {
$field = mb_convert_encoding($field, 'UTF-8', $enc);
}
// 移除 BOM
$field = preg_replace('/^\\xEF\\xBB\\xBF/', '', $field);
return trim($field);
}
?>
// 匯出給 Excel 開啟:建議 UTF-8 with BOM
$bom = "\xEF\xBB\xBF";
$fp = fopen('export.csv', 'w');
fwrite($fp, $bom);
foreach ($rows as $row) {
fputcsv($fp, $row);
}
fclose($fp);
| 編碼別名 | 說明 | mb_detect_encoding 參數 |
|---|---|---|
| Big5 | 繁體中文常用 | BIG5, BIG-5 |
| CP950 | Windows 繁體中文代碼頁 | CP950 |
| GBK | 簡體中文擴充 | GBK |
| CP936 | Windows 簡體中文代碼頁 | CP936 |
| UTF-8 | 通用、推薦 | UTF-8 |
function detect_csv_encoding($file, $sampleLines = 100) {
$fp = fopen($file, 'r');
$encodings = [];
for ($i = 0; $i < $sampleLines && ($line = fgets($fp)); $i++) {
$enc = mb_detect_encoding($line, 'UTF-8, BIG5, GBK, CP950', true);
if ($enc) $encodings[$enc] = ($encodings[$enc] ?? 0) + 1;
}
fclose($fp);
arsort($encodings);
return array_key_first($encodings) ?: 'UTF-8';
}