对于数百万条数据量的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')) {
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行开始 www.111cn.net读取
$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大文件导入数据库的示例的更多相关文章

  1. PHP快速按行读取CSV大文件的封装类分享(也适用于其它超大文本文件)

    CSV大文件的读取已经在前面讲述过了(PHP按行读取.处理较大CSV文件的代码实例),但是如何快速完整的操作大文件仍然还存在一些问题. 1.如何快速获取CSV大文件的总行数? 办法一:直接获取文件内容 ...

  2. 用脚本将excel,csv等文件导入数据库

    文章转自 http://blog.csdn.net/lky5387/article/details/6043009 1.--导excel文件 select  订单编码 from OpenRowSet( ...

  3. 本地sql大文件导入数据库

    mysql中配置my.ini interactive_timeout = 120 wait_timeout = 120 max_allowed_packet = 32M 导入sql运行命令 sourc ...

  4. C# ASP.NET CSV文件导入数据库

    原文:C# ASP.NET CSV文件导入数据库 using System; using System.Collections.Generic; using System.Text; using Sy ...

  5. 【DRP】採用dom4j完毕XML文件导入数据库

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/lantingxv_jing/article/details/37762523     xml文件在如 ...

  6. Java调用SqlLoader将大文本导入数据库

    Java调用SqlLoader将大文本导入数据库 业务场景:将一千万条数据,大约500M的文本文档的数据导入到数据库 分析:通过Java的IO流解析txt文本文档,拼接动态sql实现insert入库, ...

  7. 用php导入10W条+ 级别的csv大文件数据到mysql。导出10W+级别数据到csv文件

    转自:http://blog.csdn.net/think2me/article/details/12999907 1. 说说csv 和 Excel 这两者都是我们平时导出或者导入数据一般用到的载体. ...

  8. 利用mongoimport命令导入csv大文件

    最近我同事做了一个PHP项目,其中有一个功能是 上传excel文件并将数据导入mongodb某个集合中. 通常的做法是 写一个上传文件的页面,然后后端 读取 这个文件,利用phpexcel类库将这个e ...

  9. CSV文件导入数据库和导出数据库

    实例一: <?php $filename = 'test'; //导出文件 header("Content-type: application/vnd.ms-excel; charse ...

随机推荐

  1. zoj3231 Apple Transportation(最大流)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Apple Transportation Time Limit: 1 Second ...

  2. (转+原)ipp "No dlls were found in the Waterfall procedure"

    转自: http://blog.csdn.net/hua_007/article/details/9112909 1,吧 dll的目录放到系统环境变量中 intel 的官方推荐.验证是ok的. --- ...

  3. 表单提交---前端页面模拟表单提交(form)

    有些时候我们的前端页面总没有<form></form>表单,但是具体的业务时,我们又必须用表单提交才能达到我们想要的结果,LZ最近做了一些关于导出的一些功能,需要调用浏览器默认 ...

  4. ThreadLocal的使用 .

    早在Java 1.2推出之时,Java平台中就引入了一个新的支持:java.lang.ThreadLocal,给我们在编写多线程程序时提供了一种新的选择.使用这个工具类可以很简洁地编写出优美的多线程程 ...

  5. shell脚本练习(autocert)

    #!/bin/bash#By Spinestars#20131118 #name:ca_cert#certficate ca cd /etc/pki/CA/auto num=$RANDOM mv ./ ...

  6. ASP.NET MVC 4.0 学习1-C#基础语法

    1,方法多載,相同的方法名稱,不同的參數類型.數量 class Program { static void Main(string[] args) { Program newObject = new ...

  7. Java 之String.valueOf(obj)

    实例代码如下: String str = null; String uSelectDate = String.valueOf(str); System.out.println("====== ...

  8. Structs2中Action返回json到前台方法

    1.传统方式JSON输出 这一点跟传统的Servlet的处理方式基本上一模一样,代码如下 01 public void doAction() throws IOException{ 02        ...

  9. 用日志文件备份sqlserver

    USE [TestDB] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO )) as ) ),),)),)+ '.bak' backup dat ...

  10. 转(havel 算法)

    http://www.cnblogs.com/wally/p/3281361.html poj 1659(havel算法) 题目链接:http://poj.org/problem?id=1659 思路 ...