Advertisement
rfv123

34490225/read-last-n-lines-of-csv-file-in-php

Dec 28th, 2015
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 3.08 KB | None | 0 0
  1. <?php // http://stackoverflow.com/questions/34490225/read-last-n-lines-of-csv-file-in-php
  2.  
  3. // include __DIR__ .'/__bootstrap__.php';
  4.  
  5. define('SOURCE_CSV_FILE', 'P:/temp' .'/test.csv');
  6.  
  7. $reqdlastLines      =  125;  // how many lines line we want
  8.  
  9. $estLineLen         = 1024;  // guess at the line length
  10.  
  11. $avgLineCnt         =   20;  // number of lines to read to estimate the length
  12. $avgLineCntStartPos =   10;  // number of lines to skip at the start of the file
  13.  
  14. $avgLineLen         =   -1;  // measured line length from file records
  15.  
  16. /* --------------------------------------------------------------------------
  17.  * Output array...
  18.  */
  19. $lastRecords = array();
  20.  
  21. /* --------------------------------------------------------------------------
  22.  * The source file:
  23.  *   o Information
  24.  *   o the actual file handle
  25.  */
  26. $finfo = new SplFileInfo(SOURCE_CSV_FILE);
  27. $file = fopen(SOURCE_CSV_FILE, 'rb');
  28.  
  29. /* ---------------------------------------------------------------------------
  30.  *  Get an estimate of the average line length
  31.  */
  32. // skip first few records...
  33. for ($recNo = $avgLineCntStartPos; $recNo > 0; $recNo--) {
  34.     $ignore = fgets($file);
  35. }
  36. // estimate the record length based on about 20 records...
  37. $totLen = 0;
  38. $recCnt = 0;
  39. for ($recNo = $avgLineCnt; $recNo > 0; $recNo--, $recCnt ++) {
  40.     $rec = fgets($file);
  41.     $totLen += strlen($rec);
  42. }
  43.  
  44. // get the average line length
  45. $avgLineLen = max($estLineLen, intval($totLen / $recCnt));
  46.  
  47. /* ---------------------------------------------------------------------------
  48.  * Position the file pointer to the start of a record near the end of the file
  49.  */
  50.  
  51. // how far from the end of the file we should be...
  52. $seekPos = $avgLineLen * $reqdlastLines;
  53. $allOk = fseek($file,  $seekPos * -1, SEEK_END); // Must be *negative* position
  54.  
  55. // now find the start of the next line...
  56. // by finding first none control character...
  57.  
  58. $readCh = chr(0);
  59. $readChCnt = 0;
  60. while ($readCh !== false && $readCh < chr(32)) {
  61.     $readCh = fgetc($file);
  62.     $readChCnt++;
  63.  
  64.     if ($readChCnt > $avgLineLen) { // what happened?
  65.         die('looking for a record: read characters: '. $readChCnt);
  66.     }
  67. }
  68.  
  69. //  and the read rest of this record to get to get to the start of the next record...
  70. $rec = fgets($file);
  71.  
  72. /* ---------------------------------------------------------------------------
  73.  *  Now we start processing records... yeah!
  74.  *
  75.  *  There needs to $reqdLastLines and no more...
  76.  */
  77. while (!feof($file)) {
  78.     $record = fgetcsv($file);
  79.     if ($record === false) { // end of the file - 'belt and braces'
  80.         break;
  81.     }
  82.  
  83.     // ensure there are 'required last records' in the array an no more...
  84.     if (count($lastRecords) >= $reqdlastLines) {
  85.         array_shift($lastRecords); // lose earliest record
  86.     }
  87.  
  88.     $lastRecords[] = $record;
  89. }
  90. // we are done...
  91. fclose($file);
  92.  
  93. /* ---------------------------------------------------------------------------
  94.  *  Process the last records...
  95.  *
  96.  *  Write to file etc. Here I just dump them
  97.  */
  98. // statistics..
  99. var_dump($avgLineLen, $seekPos, $finfo->getSize(), $lastRecords);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement