【问题标题】:fgetcsv / fopen in reversefgetcsv / fopen 反向
【发布时间】:2012-07-25 13:30:49
【问题描述】:

我正在尝试做这个确切的功能,只想能够显示文档的最后 20 行?

    $file = fopen("/tmp/$importedFile.csv","r");
    while ($line =  fgetcsv($file))
    {
        $i++;
        $body_data['csv_preview'][] = $line;
        if ($i > 20) break;
    }
    fclose($file);

我已尝试更改$file = fopen("/tmp/$importedFile.csv","r"); 中的"r",但似乎只有将指针放置在读取和写入位置的变化。

我觉得这很容易。我很抱歉。

【问题讨论】:

    标签: php codeigniter csv


    【解决方案1】:

    一种方法是使用SqlFileObject。首先,您需要知道文件中有多少行,您可以这样计算:

    $filename = "/tmp/$importedFile.csv";
    
    // Create a new object for the file
    $file = new SplFileObject( $filename, "r");
    
    $lines = 0;
    while ( !$file->eof()) {
       $file->fgets();
       $lines++;
    }
    

    现在您知道文件中有$lines 行数。然后,您必须寻找到$lines - 20 行号,并读取您的 CSV 数据直到 EOF,如下所示:

    $file->seek( $lines - 20);
    while ( !$file->eof()) { 
        $body_data['csv_preview'][] = $file->fgetcsv();
    }
    

    也许有一种更有效的方法来计算$lines。另外,在尝试seek()$lines - 20 之前,您应该确认文件中有超过20 行。

    【讨论】:

      【解决方案2】:

      您的代码返回前 20 行。尝试修改最后 20 行

      if($i > 20)
         array_shift($body_data['csv_preview'])
      

      【讨论】:

        【解决方案3】:

        我想出了这个:

        $file = fopen("/tmp/$importedFile.csv","r");
        $start = count( file( $file ) ) - 20;
        $i = 0;
        while ($line =  fgetcsv($file)) {
            $i++;
            if ( $i > $start ) $body_data['csv_preview'][] = $line;
        }
        fclose($file);
        //Body_data has now the last 20 lines.
        

        希望对你有帮助

        【讨论】:

        • +1 (从未使用过该 file() 函数),但您可以通过从file( $file ) 生成的数组中读取最后 20 个元素然后使用 str_getcsv 进行解析来进一步简化这一点行,无需重新读取文件。唯一潜在的缺点是需要读取大量 csv 文件时会消耗内存。
        【解决方案4】:

        这是一种方式

        $fileend = array();
        $file = fopen("/tmp/$importedFile.csv","r");
        while ($line =  fgetcsv($file))
        {
            // we have a line, so if $fileend already contains the required number
            // of lines we have to make some room.
            if (count($fileend) > 20) {
                $fileend=array_shift($fileend);
            }
            // add freshly read line to array's end
            array_push($fileend,$line);
        }
        fclose($file);
        // at this point $fileend will contain the 20 last lines of the file.
        

        我不能保证它会快得令人眼花缭乱......

        一种更快的方法是将行存储在一个固定大小的循环缓冲区中,这比听起来容易

        $i=0;
        while ($line =  fgetcsv($file))
        {
            // store as linenumber modulo 20 'th element in array
            $circularbuffer[$i % 20] = $line;
            $i++;
        }
        

        然后阅读它

        // must start reading after last written element, $i has the correct value.
        // and we will read 20 times - same modulo calculation to "circulate" buffer
        for ($j=$i;$j<$i+20;$j++) {
            $body_data['csv_preview'][] = $circularbuffer[$j%20];
        }
        

        显然这里最大的优势是您只读取文件一次,而且我认为读取操作是迄今为止该函数中成本最高的部分(在执行时间上)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2023-03-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-01-08
          • 1970-01-01
          相关资源
          最近更新 更多