秒讀 Excel 百萬資料(第一篇)

華賢發表於2019-11-21

讀取前的準備工作

1. 檔案型別屬於 .xls 、.xlsx,需要用辦公軟體 WPS 或 Office 將檔案另存為 .csv 型別。不能直接重新命名修改檔案型別,直接重新命名修改檔案型別會導致資料格式不相容,Windows上可以正常開啟閱讀,Linux上讀取資料會出現資料轉碼不成功,無法正常讀取資料

2. Excel檔案型別必須是 .csv

正式開始(主要程式碼在後面)

伺服器配置:\
CPU: 4核\
記憶體: 16 GiB\
頻寬: 6Mbps

<?php

ini_set('memory_limit', -1);

//開始執行時間
$stime = microtime(true);

//開始位置獲取(記憶體)
$start_memory = memory_get_usage();

//檔案路徑
$filePath = '你的檔案路徑';

//傳入檔案路徑
$readerCsv = new ReaderCsv($filePath);

//讀取csv檔案
$readerCsv->readCsv();

//獲取Excel資料
$excelData = $readerCsv->getExcelData();

//結束執行時間
$etime     = microtime(true);
$timeUsage = $etime - $stime;

//末尾位置獲取
$end_memory = memory_get_usage();
$use_memory = $end_memory - $start_memory;
$use_memory = $use_memory / 1024 / 1024;

dd('共讀取資料: '.$readerCsv->getRow().'行', '共耗時: '.$timeUsage.'秒', '共消耗記憶體: '.$use_memory.'MB');


執行結果

Excel表總列數:31

104w資料

image.png

80w資料

image.png

60w資料

image.png

40w資料

image.png

20w資料

image.png

主要程式碼

<?php

namespace App\Excel;

class ReaderCsv
{

    /**
     * 陣列鍵值
     * @var int
     */
    protected $row = 0;

    /**
     * Excel源資料
     * @var array
     */
    protected $excelData = [];

    /**
     * 檔案路徑
     * @var
     */
    protected $path;

    /**
     * ReaderCsv constructor.
     * @param $path
     */
    public function __construct($path)
    {
        $this->path = $path;
    }

    /**
     * 讀取CSV檔案
     */
    public function readCsv()
    {
        //陣列鍵值
        $row = $this->row;

        //Excel陣列
        $excelData = [];

        //開啟檔案
        $file = fopen($this->path, 'r');

        //從檔案指標中讀入一行並解析 CSV 欄位
        //fgetcsv 解析讀入的行並找出 CSV 格式的欄位然後返回一個包含這些欄位的陣列。
        while ($data = fgetcsv($file)) {
            //統計一行資料有多少列
            $columnSize = count($data);

            for ($i = 0; $i < $columnSize; $i++) {
                //轉換字元的編碼 && 賦值Excel源資料
                $excelData[$row][$i] = mb_convert_encoding(
                    $data[$i],
                    'UTF-8',
                    'gb2312'
                );
            }
            $row++;
        }

        $this->row = $row;

        //關閉一個已開啟的檔案指標
        fclose($file);

        $this->excelData = $excelData;
    }

    /**
     * 獲取Excel源資料
     * @return array
     */
    public function getExcelData()
    {
        return $this->excelData;
    }

    /**
     * 獲取總行數
     * @return int
     */
        public function getRow()
    {
        return $this->row;
    }
}


最後

如果業務需要讀取大Excel檔案建議使用上面的方法,小的Excel檔案還是建議使用PhpSpreadsheet

這篇說的是一次讀取整個Excel檔案(還是會有不足的地方),後續會更新第二篇按照“塊”的方式讀取。

第一次分享,有不好的地方請多多見諒~_~

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章