欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

CSV导入十万条数据到数据库

程序员文章站 2024-03-23 09:01:46
...

PHP导入Excel表格,很多都使用PHPExcel这个类库。但是如果Excel表格数据库多的话(比如一万条),就会导致内存溢出。加大PHP的使用内存空间,也不是根本的解决办法。所以我们需要将Excel保存成CSV文件,在利用fgetcsv()函数进行分页导入,就不会发生内存溢出的情况。

1 、转成CSV,直接另存为CSV文件即可。

CSV导入十万条数据到数据库

2、CSV类的封装
获取CSV总行数,设置分页大小。所以封装一个操作CSV的类。如下:

<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/10/11
 * Time: 10:29
 */

namespace app\common\service;


class Csv
{

        private $csv_file;
        private $spl_object = null;
        private $error;

        public function __construct($csv_file = '') {
            if($csv_file && file_exists($csv_file)) {
                $this->csv_file = $csv_file;
            }
        }

        public function set_csv_file($csv_file) {
            if(!$csv_file || !file_exists($csv_file)) {
                $this->error = 'File invalid';
                return false;
            }
            $this->csv_file = $csv_file;
            $this->spl_object = null;
        }

        public function get_csv_file() {
            return $this->csv_file;
        }

        private function _file_valid($file = '') {
            $file = $file ? $file : $this->csv_file;
            if(!$file || !file_exists($file)) {
                return false;
            }
            if(!is_readable($file)) {
                return false;
            }
            return true;
        }

        private function _open_file() {
            if(!$this->_file_valid()) {
                $this->error = 'File invalid';
                return false;
            }
            if($this->spl_object == null) {
                $this->spl_object = new \SplFileObject($this->csv_file, 'rb');
            }
            return true;
        }

        /**
         * 获取csv行
         * @param int $length
         * @param int $start
         * @return array|bool
         */
        public function get_data($length = 0, $start = 0) {
            if(!$this->_open_file()) {
                return false;
            }
            $length = $length ? $length : $this->get_lines();
            $start = $start - 1;
            $start = ($start < 0) ? 0 : $start;
            $data = array();
            $this->spl_object->seek($start);
            while ($length-- && !$this->spl_object->eof()) {
                $data[] = $this->spl_object->fgetcsv();
                $this->spl_object->next();
            }
            return $data;
        }

        public function get_lines() {
            if(!$this->_open_file()) {
                return false;
            }
            $this->spl_object->seek(filesize($this->csv_file));
            return $this->spl_object->key();
        }

        public function get_error() {
            return $this->error;
        }


}

三、分页导入
将EXCEL转成CSV,会乱码,所以要用**mb_convert_encoding()**函数进行转化。

function changeCharset($value){
	$value = mb_convert_encoding($value,'UTF-8','GBK');
}
public function importData (){
    $t1 = microtime(true);
    $filePath = ROOT_PATH . 'public' . "/11.csv";//上传的excel路径

    $csv = new Csv($filePath);

    $total =  $csv->get_lines();//读取总行数

    $pagesize = 100;//一次导入的大小
    $page = ceil($total/$pagesize);
    for($i=0;$i<$page;$i++){
        $data = $csv->get_data($pagesize,$i*$pagesize);//获取表格的行数据

        if(empty($data))break;
        $insert=[];
        foreach($data as $k => $temp){

            array_walk($temp,"changeCharset");

            if(empty($temp[0])){
                continue;
            }

            $insert[] = array(
                'id'           => $temp[0],
                'company_name' => $temp[1],
                'industry'     => $temp[2],
                'contacts'     => $temp[3],
                'phone'        => $temp[4],
                'mail'         => $temp[5],
                'company_address'=> $temp[6],
                'province'     => $temp[7],
                'city'         => $temp[8],
                'district'     => $temp[9],
                'street'       => $temp[10],
                'street_number' => $temp[11],
                'lng'          => $temp[12],
                'lat'           => $temp[13]
            );


        }

        db("import")->insertAll($insert);
    }

    $t2 = microtime(true);
    echo '耗时'.round($t2-$t1,3).'秒<br>';
    die;

}