首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

Linux 下 fgetcsv() 讀取中文 CSV 欄位為空字串的解決方案:locale 設定

     編輯:PHP 相關知識

問題現象

  • CSV 檔以 Excel(Windows、GBK/Big5 編碼)編輯。
  • 伺服器為 Linux(UTF-8 環境),PHP 程式碼為 UTF-8。
  • 僅用 iconv('GBK', 'UTF-8', ...) 轉碼後,fgetcsv() 讀取中文欄位回傳空字串,英文欄位正常。

根本原因

fgetcsv() 依賴 C 語言的 setlocale() 正確解析多位元組字元。Linux 預設 locale 為 C 或 POSIX(單位元組),無法正確識別 UTF-8 中文字元邊界,導致欄位切割錯誤、中文變空字串。

解決方案:設定正確的 locale

<?php
// 1. 上傳的 CSV 通常為 GBK/Big5,先轉 UTF-8
$content = file_get_contents($tmpFile);
$content = iconv('GBK', 'UTF-8//IGNORE', $content);
file_put_contents($tmpFile, $content);

// 2. 關鍵:設定 locale 為 UTF-8 中文環境
setlocale(LC_ALL, 'zh_CN.UTF-8'); // 或 'zh_TW.UTF-8'、'en_US.UTF-8' 皆可,關鍵是 .UTF-8

// 3. 開啟檔案並讀取
$handle = fopen($tmpFile, 'r');
$headers = fgetcsv($handle); // 現在中文欄位正常

while (($row = fgetcsv($handle)) !== false) {
    // 處理每一行資料
}
fclose($handle);
?>

常見 locale 值對照

作業系統中文 UTF-8 locale
Linux (Debian/Ubuntu/CentOS)zh_CN.UTF-8、zh_TW.UTF-8
FreeBSDzh_CN.UTF-8
macOSzh_TW.UTF-8

可用 locale -a 指令查詢系統支援的 locale。

進階:自動偵測換行符號(Windows CRLF / Linux LF / Mac CR)

ini_set('auto_detect_line_endings', true); // PHP 4.3+

完整健壯範例

<?php
function readCsvRobust($filePath, $fromEncoding = 'GBK') {
    // 讀取並轉碼
    $content = file_get_contents($filePath);
    $content = iconv($fromEncoding, 'UTF-8//IGNORE', $content);
    $tmpFile = tempnam(sys_get_temp_dir(), 'csv_');
    file_put_contents($tmpFile, $content);

    // 設定 locale
    $locales = ['zh_CN.UTF-8', 'zh_TW.UTF-8', 'en_US.UTF-8', 'C.UTF-8'];
    $set = false;
    foreach ($locales as $loc) {
        if (setlocale(LC_ALL, $loc) !== false) {
            $set = true;
            break;
        }
    }
    if (!$set) {
        trigger_error('無法設定 UTF-8 locale,CSV 解析可能異常', E_USER_WARNING);
    }

    ini_set('auto_detect_line_endings', true);
    $handle = fopen($tmpFile, 'r');
    $headers = fgetcsv($handle);
    $data = [];
    while (($row = fgetcsv($handle)) !== false) {
        $data[] = array_combine($headers, $row);
    }
    fclose($handle);
    unlink($tmpFile);
    return $data;
}
?>
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved