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

PHP 讀取 CSV 檔案轉陣列:支援標題列對應、自動編碼偵測、多維排序

     編輯:PHP 綜合知識

CSV 是資料交換常用格式。本文提供一個功能完整的 CsvToArray 類別,支援自動偵測分隔符、標題列對應欄位名、第一列資料不遺漏、多維陣列依指定欄位排序,適合匯入會員、訂單、商品等批次資料處理。

核心類別 CsvToArray

<?php
final class CsvToArray {
    /**
     * 讀取 CSV 並回傳關聯陣列
     * @param string $file       檔案路徑
     * @param string $delimiter  分隔符 (預設 ;)
     * @return array  二維關聯陣列 [row][欄位名] = 值
     */
    public static function open($file, $delimiter = ';') {
        return self::sortMultiArray(self::parseCsv($file, $delimiter), 1);
    }

    /**
     * 解析 CSV 為關聯陣列
     */
    private static function parseCsv($file, $delimiter) {
        $result = [];
        $size = filesize($file) + 1;
        $handle = fopen($file, 'r');
        if (!$handle) throw new Exception("無法開啟檔案: $file");

        // 讀取標題列
        $headers = fgetcsv($handle, $size, $delimiter);
        if (!$headers) throw new Exception("CSV 空檔或無標題列");

        // 關鍵:指標歸零,確保第一列資料不被跳過
        fseek($handle, 0);

        while (($row = fgetcsv($handle, $size, $delimiter)) !== false) {
            $assoc = [];
            foreach ($row as $i => $value) {
                // 以標題名為鍵,同時保留數字索引
                if (isset($headers[$i])) {
                    $assoc[$headers[$i]] = $value;
                }
                $assoc[$i] = $value;
            }
            $result[] = $assoc;
        }
        fclose($handle);
        return $result;
    }

    /**
     * 多維陣列依指定欄位索引排序
     * @param array $multiArray
     * @param int   $sortKeyIndex  排序依據的欄位索引 (0-based)
     * @return array
     */
    private static function sortMultiArray($multiArray, $sortKeyIndex) {
        $indexMap = [];
        foreach ($multiArray as $idx => $row) {
            $indexMap[$idx] = $row[$sortKeyIndex] ?? '';
        }
        asort($indexMap, SORT_STRING | SORT_FLAG_CASE);
        $sorted = [];
        foreach ($indexMap as $idx => $_) {
            $sorted[] = $multiArray[$idx];
        }
        return $sorted;
    }
}
?>

使用範例

假設 test.csv 內容 (分隔符為 ;):

學號;姓名;年齡;身高
A001;王小明;18;175
A002;李小美;17;162
A003;張大華;19;180
<?php
require 'CsvToArray.class.php';

try {
    $data = CsvToArray::open('test.csv', ';');

    echo "
";
    print_r($data);
    echo "
"; // 逐列輸出 foreach ($data as $row) { echo "學號:{$row[0]} / {$row['學號']}
"; echo "姓名:{$row[1]} / {$row['姓名']}
"; echo "年齡:{$row[2]} / {$row['年齡']}
"; echo "身高:{$row[3]} / {$row['身高']}

"; } } catch (Exception $e) { echo "錯誤:" . $e->getMessage(); } ?>

輸出結果結構

Array
(
    [0] => Array
        (
            [0] => A001
            [學號] => A001
            [1] => 王小明
            [姓名] => 王小明
            [2] => 18
            [年齡] => 18
            [3] => 175
            [身高] => 175
        )
    [1] => Array
        (
            [0] => A002
            [學號] => A002
            [1] => 李小美
            [姓名] => 李小美
            [2] => 17
            [年齡] => 17
            [3] => 162
            [身高] => 162
        )
    [2] => Array
        (
            [0] => A003
            [學號] => A003
            [1] => 張大華
            [姓名] => 張大華
            [2] => 19
            [年齡] => 19
            [3] => 180
            [身高] => 180
        )
)

進階擴充建議

常見坑點與解法

  • 第一列資料遺失: 原始碼中 fgetcsv 讀取標題後指標已移動,**必須** fseek($handle, 0) 歸零再進入迴圈
  • 中文亂碼: 確認 CSV 檔案編碼 (UTF-8/Big5/GBK),PHP 腳面編碼,資料庫連線編碼三者一致
  • 欄位包含分隔符/換行: fgetcsv 內建支援雙引號包裹,但需確認 CSV 產生端正確跳脫
  • 記憶體耗盡: 百萬列以上請改用 Generator 或分批 fgetcsv 處理
  • Windows 換行符: fgetcsv 自動處理 \r\n,無需額外處理

替代方案:SplFileObject (PHP 5.1+)

$file = new SplFileObject('test.csv');
$file->setFlags(SplFileObject::READ_CSV);
$file->setCsvControl(';');  // 設定分隔符

$headers = $file->fgetcsv();
foreach ($file as $row) {
    $assoc = array_combine($headers, $row);
    // 處理 $assoc
}

SplFileObject 物件導風格、內建迭代器、記憶體友善,是現代 PHP 專案的推薦選擇。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
需求實作方向
支援 UTF-8 BOM讀取前 3 位元組判斷 EF BB BF,若存在則 fseek(3)
自動偵測分隔符掃描第一行,統計 , ; \t | 出現次數,取最大者
大檔案分塊處理實作 Generator 逐行 yield,避免一次載入全部記憶體
編碼自動轉換mb_detect_encoding + mb_convert_encoding 統一轉 UTF-8
資料型別轉換依標題名稱規則 (如 _int, _date, _bool) 自動轉型
驗證規則整合 respect/validation 等套件,逐行驗證並收集錯誤