好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

PHP读取CSV大文件导入数据库的示例 - php高级应用

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

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

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

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

/**    * 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 ,  'r' )) {       //开源代码phpfensi测试数据         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( 'path/bigfile.csv' , 10, 2000000);    print_r( $data ); 

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

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

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

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

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

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

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

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

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

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

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

$csv_file  =  'path/bigfile.csv' ;  $start  = 100000;   // 从第100000行开始 HdhCmsTestphpfensi测试数据读取   $num  = 100;     // 读取100行   $data  =  array ();  $spl_object  =  new  SplFileObject( $csv_file ,  'rb' );  $spl_object ->seek( $start );  while  ( $num -- && ! $spl_object ->eof()) {    $data [] =  $spl_object -> fgetcsv ();    $spl_object ->next();  }  print_r( $data ); 

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

class  CsvReader {    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;   }      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 ( 'CsvReader.class.php' );    $csv_file  =  'path/bigfile.csv' ;    $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即可.

查看更多关于PHP读取CSV大文件导入数据库的示例 - php高级应用的详细内容...

  阅读:49次