首頁 >php教程 >php手册 >PHP快速按行读取CSV大文件的封装类分享

PHP快速按行读取CSV大文件的封装类分享

WBOY
WBOY原創
2016-06-13 09:38:02958瀏覽

 这篇文章主要介绍了一个PHP快速按行读取CSV大文件的封装类,这个类同时也适用于其它体积较大的文本文件,需要的朋友可以参考下

CSV大文件的读取已经在前面讲述过了(PHP按行读取、处理较大CSV文件的代码实例),但是如何快速完整的操作大文件仍然还存在一些问题。

 

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行开始读取

$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);

 

 

3、综合上面两点,整理成一个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

  $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即可。

 

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn