在php中跳过n行csv文件

时间:2016-05-25 06:18:06

标签: php csv rows skip

我有一个csv文件,其行数约为500000。我需要做的是在第一个循环中取前100行并操纵行(例如,将前100个ID发送到API并保存响应)。在第二个循环中,跳过前100行(已经采用)并再占用100行并向Web服务发送请求。类似地,在第三个循环中,跳过前200行并再占用100行并向Web服务发送请求,依此类推......

我可以使用以下代码获取单行。 (测试:效果很好)

if (($handle = fopen($filename, "r")) !== FALSE) {
    $id   = 1;
    $line = fgetcsv($handle); //skip first row

    //fetch data from each row
    while (($data = fgetcsv($handle, ",")) !== FALSE) {
        $hotel_id   = $data[0];
        //call service to request to web service
        $hotelDetailRequest = (new \Services\Hotel\Hotel)->getHotelStaticData($hotel_id);
        //do stuff to response
    }
}

同样,我可以跳过一些初始行,就像我跳过第一行添加

一样
$line = fgetcsv($handle);
$line = fgetcsv($handle);
$line = fgetcsv($handle);

但是,这不是我上面解释的预期结果。我正在使用PHP(Laravel)。我用谷歌搜索,但找不到符合我标准的任何合适品。有没有人面临同样的问题?

任何帮助将不胜感激。谢谢

2 个答案:

答案 0 :(得分:1)

这是一个适合您的解决方案:

<?php
$filename = "the_data.csv";
$chunk_size = 200;

// parse csv file into an array
$csv_data = array_map('str_getcsv', file($filename));

// split data array into chunks
$chunked_data = array_chunk($csv_data, $chunk_size);

foreach($chunked_data as $chunk){

    // here you have $chunk_size row data
    // iterate in chunk
    foreach($chunk as $row ){
        $hotel_id   = $row[0];

        // send request to web service
        // do stuff to response
    }

    sleep(1);
}
?>

答案 1 :(得分:0)

您可以将SplFileObject->seek($start)结合使用。我们可以参考您将与普通MySQL数据库一起使用的limit/offset关系;这是一个例子:

$file = SplFileObject("myfile.csv");

$rules = DB::query("select * from file_rules where id = 1");

if ($rules->limit) {
    $file->seek($rules->offset);
}

此时,您可以执行一个简单的循环,并将索引计数与偏移值进行比较。

foreach ($file as $index => $row ) {
    if ($file->valid() && $index <= $rules->limit ) {
        //perform your calls to do your API request
    }
}

完成后,只需更新您的数据库记录:

DB::query('update file_rules set offset='.$rules->offset+$rules->limit.' where id =1');

这是它的主旨。用您自己的代码替换我的DB伪代码。这将允许您将其作为CRON执行,并使用数据库作为交互点来获取limit/offset并使用seek将其应用于循环以进一步节省内存。