【问题标题】:PHP skip lines while readingPHP在阅读时跳过行
【发布时间】:2016-07-20 19:28:06
【问题描述】:

我试图找到一种从 csv 文件读取的快速方法,首先跳过几行,读取大约 20 行,然后停止读取。目前唯一的解决方案是使用 fread,效率很低。

【问题讨论】:

  • 为什么要避免fread?这就是fgetcsv() 无论如何都会在内部使用的。一种或另一种方式,必须将这些行读入 php,以便它可以找出换行符的位置。如果您选择跳过/忽略这些行,那不是 php 的问题 - 必须读取数据。
  • 你可以用file()将整个文件读入一个数组,然后用array_slice()得到你想要的行。
  • 但是如果文件很大,那会比较慢和浪费。你原来的方式可能是最好的。
  • 问题是文件不是按行排列而是按块排列,要跳过多行,您需要扫描文件以找到换行符,因此使用阅读器读取行并丢弃它们几乎是不可避免的。

标签: php csv


【解决方案1】:

滚动浏览尊重特定 CSV 格式的 CSV 的唯一方法是调用解析器。最快的 CSV 解析器是内置的fgetcsv。因此,这将是所有可能的可靠方法中最快的:

function csv_slice($fp, $offset = 0, $length = 0) {
    $i = 0;
    while (false !== ($row = fgetcsv($fp))) {
        if ($i++ < $offset) continue;
        if (0 < $length && $length <= ($i - $offset - 1)) break;
        yield $row;
    }
}

像这样使用:

$fp = fopen('file.csv', 'r');
print_r(
    iterator_to_array(
        csv_slice($fp, 5, 2) // start after 5th row, return 2 rows
    )
);
fclose($fp);

我在这里使用了生成器来保持低内存消耗。如果您愿意,可以轻松替换为临时数组。

如果您可以对行尾做出一些假设,那么您可以逐字节读取,直到找到行尾的范围。但是,坦率地说,我不会那样做。

【讨论】:

    【解决方案2】:

    假设你下面有这段代码

    <?php
    
        $row = 1;
        if (($handle = fopen("ptt.csv", "r")) !== FALSE) {
            while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
                $num = count($data);
                $row++;
    
                for ($c=0; $c < $num; $c++) {
                    echo "<TR>";    // OPEN ROW
                    if(strpos($data[$c], 'Finished') !== false) {
                        $c++;
                        echo "<TD nowrap>" . $data[$c] . "</TD>"; 
                    }else{
                        echo "<TD nowrap>" .  $data[$c] . "</TD>";
                    }
                    echo "</TR>";    // CLOSE ROW
                }
            }
            fclose($handle);
        }
    ?>
    

    如果你添加

        if($row == 20){ $row++; continue; }
    

    while 循环之后

        while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
           if($row == 20){ $row++; continue; }
    

    现在,假设你想从第 20 行开始,它会继续阅读

    让我们再举一个例子。如果你想从 1 开始在第 40 行停止阅读,你可以插入

       if($row == 40){ $row++; exit; }
    
    【解决方案3】:

    尝试使用file()。它将读取文件的所有行,然后您可以按照自己的方式读取它。例如:

    $lines = file("myfile.txt");
    $lineCounter = count($lines);
    
    if($lineCounter > 20){
    
        $startsAt = 21; //Skip 20 lines
        for($i = $startsAt; $i < $lineCounter; $i++){
            $line = $lines[$i];
            //Do whatever you want with the line contents
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2015-08-27
      • 1970-01-01
      • 2018-06-20
      • 2013-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多