Heim >php教程 >php手册 >PHP读取CSV大文件导入数据库的示例

PHP读取CSV大文件导入数据库的示例

WBOY
WBOYOriginal
2016-05-25 16:38:221762Durchsuche

文章详细介绍了csv文件在php中快速导入到mysql数据库中的例子,虽然从最简单的几百MB的到最后使用插件实现几个GB数据导入中间有一些嗑碰了,但结果还是好的.

对于数百万条数据量的CSV文件,文件大小可能达到数百M,如果简单读取的话很可能出现超时或者卡死的现象.

为了成功将CSV文件里的数据导入数据库,分批处理是非常必要的,下面这个函数是读取CSV文件中指定的某几行数据,代码如下:

<?php
/** 
 * csv_get_lines 读取CSV文件中的某几行数据
 * @param $csvfile csv文件路径
 * @param $lines 读取行数
 * @param $offset 起始行数
 * @return array
 *
 */
function csv_get_lines($csvfile, $lines, $offset = 0) {
    if (!$fp = fopen($csvfile, &#39;r&#39;)) {
        //开源代码phprm.com
        return false;
    }
    $i = $j = 0;
    while (false !== ($line = fgets($fp))) {
        if ($i++ < $offset) {
            continue;
        }
        break;
    }
    $data = array();
    while (($j++ < $lines) && !feof($fp)) {
        $data[] = fgetcsv($fp);
    }
    fclose($fp);
    return $data;
}
//调用方法:
$data = csv_get_lines(&#39;path/bigfile.csv&#39;, 10, 2000000);
print_r($data);
?>

函数主要采用行定位的思路,通过跳过起始行数来实现文件指针定位,至于数据如何入库本文不再详细讲述.

上述函数对500M以内的文件进行过测试,运行通畅,对于1GB的文件发现有点慢了,于是再接着找方法.

如何快速完整的操作大文件仍然还存在一些问题.

1、如何快速获取CSV大文件的总行数?

办法一:直接获取文件内容,使用换行符进行拆分得出总行数,这种办法对小文件可行,处理大文件时不可行;

办法二:使用fgets一行一行遍历,得出总行数,这种办法比办法一好一些,但大文件仍有超时的可能;

办法三:借助SplFileObject类,直接将指针定位到文件末尾,通过SplFileObject::key方法获取总行数,这种办法可行,且高效。

具体实现方法,代码如下:

$csv_file = &#39;path/bigfile.csv&#39;; 
$spl_object = new SplFileObject($csv_file, &#39;rb&#39;); 
$spl_object->seek(filesize($csv_file)); 
echo $spl_object->key();

2、如何快速获取CSV大文件的数据?

仍然使用PHP的SplFileObject类,通过seek方法实现快速定位,代码如下:

$csv_file = &#39;path/bigfile.csv&#39;; 
$start = 100000;  // 从第100000行开始 www.phprm.com读取 
$num = 100;    // 读取100行 
$data = array(); 
$spl_object = new SplFileObject($csv_file, &#39;rb&#39;); 
$spl_object->seek($start); 
while ($num-- && !$spl_object->eof()) { 
 $data[] = $spl_object->fgetcsv(); 
 $spl_object->next(); 
}

print_r($data); 

综合上面两点,整理成一个csv文件读取的类,代码如下:

<?php
class CsvReader {
    private $csv_file;
    private $spl_object = null;
    private $error;
    public function __construct($csv_file = &#39;&#39;) {
        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 = &#39;File invalid&#39;;
            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 = &#39;&#39;) {
        $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 = &#39;File invalid&#39;;
            return false;
        }
        if ($this->spl_object == null) {
            $this->spl_object = new SplFileObject($this->csv_file, &#39;rb&#39;);
        }
        return true;
    }
    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;
    }
}
?>

调用方法如下:

include(&#39;CsvReader.class.php&#39;); 
$csv_file = &#39;path/bigfile.csv&#39;; 
$csvreader = new CsvReader($csv_file); 
$line_number = $csvreader->get_lines(); 
$data = $csvreader->get_data(10); 
echo $line_number, chr(10); 
print_r($data);

其实,上述CsvReader类并不只针对CSV大文件,对于其他文本类型的大文件或超大文件同样可用,前提是将类中fgetcsv方法稍加改动为current即可.


教程链接:

随意转载~但请保留教程地址★

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn