2013-12-13 17 views
7

Ho un file txt che voglio leggere a ritroso, attualmente sto usando questo:righe di file Legge indietro (f gets) con php

$fh = fopen('myfile.txt','r'); 
while ($line = fgets($fh)) { 
    echo $line."<br />"; 
} 

Emette tutte le linee nel mio file.
Voglio leggere le righe dal basso verso l'alto.

C'è un modo per farlo?

risposta

10

Primo modo:

$file = file("test.txt"); 
$file = array_reverse($file); 
foreach($file as $f){ 
    echo $f."<br />"; 
} 

Seconda Way (a):

Per invertire completamente un file:

 
$fl = fopen("\some_file.txt", "r"); 
for($x_pos = 0, $output = ''; fseek($fl, $x_pos, SEEK_END) !== -1; $x_pos--) { 
    $output .= fgetc($fl); 
    } 
fclose($fl); 
print_r($output); 

Seconda Way (b): Certo, volevi l'inversione riga per riga ...

 

$fl = fopen("\some_file.txt", "r"); 
for($x_pos = 0, $ln = 0, $output = array(); fseek($fl, $x_pos, SEEK_END) !== -1; $x_pos--) { 
    $char = fgetc($fl); 
    if ($char === "\n") { 
     // analyse completed line $output[$ln] if need be 
     $ln++; 
     continue; 
     } 
    $output[$ln] = $char . ((array_key_exists($ln, $output)) ? $output[$ln] : ''); 
    } 
fclose($fl); 
print_r($output); 

+0

modo 'a +' sposta il cursore alla fine del file per voi :) (ma c'è un bug che il cursore viene spostato dopo il primo I/O, non immediatamente) –

4

provare qualcosa di più semplice come questo ..

print_r(array_reverse(file('myfile.txt'))); 
1

Se il file non è così grande che si può usare file():

$lines = file($file); 
for($i = count($lines) -1; $i >= 0; $i--){ 
    echo $lines[$i] . '<br/>'; 
} 

Tuttavia, questo richiede l'intero file di essere in memoria, che è perché non è adatto per file veramente grandi.

4

Ecco la mia soluzione per la stampa del file all'indietro. È piuttosto compatibile con la memoria. E sembra più leggibile (IMO [= a mio parere]).

Passa attraverso il file all'indietro, conta i caratteri fino all'inizio di una riga o all'inizio del file e quindi legge e stampa quella quantità di caratteri come una linea, quindi sposta il cursore indietro e legge un'altra riga come quella ...

if($v = @fopen("PATH_TO_YOUR_FILE", 'r')){ //open the file 
    fseek($v, 0, SEEK_END); //move cursor to the end of the file 
    /* help functions: */ 
    //moves cursor one step back if can - returns true, if can't - returns false 
    function moveOneStepBack(&$f){ 
     if(ftell($f) > 0){ fseek($f, -1, SEEK_CUR); return true; } 
     else return false; 
    } 
    //reads $length chars but moves cursor back where it was before reading 
    function readNotSeek(&$f, $length){ 
     $r = fread($f, $length); 
     fseek($f, -$length, SEEK_CUR); 
     return $r; 
    } 

    /* THE READING+PRINTING ITSELF: */ 
    while(ftell($v) > 0){ //while there is at least 1 character to read 
     $newLine = false; 
     $charCounter = 0; 

     //line counting 
     while(!$newLine && moveOneStepBack($v)){ //not start of a line/the file 
     if(readNotSeek($v, 1) == "\n") $newLine = true; 
     $charCounter++;    
     } 

     //line reading/printing 
     if($charCounter>1){ //if there was anything on the line 
     if(!$newLine) echo "\n"; //prints missing "\n" before last *printed* line    
     echo readNotSeek($v, $charCounter); //prints current line 
     } 

    } 
    fclose($v); //close the file, because we are well-behaved 
    } 

Naturalmente sostituire PATH_TO_YOUR_FILE con il proprio percorso al file, @ viene utilizzato quando si apre il file, perché quando il file non si trova o non può essere aperto - viene sollevato avvertimento - se si desidera visualizzare questo avviso - basta rimuovere il surpressore di errore '@'.

+0

Grazie. Penso che questa sia la soluzione migliore. – Luvias

+0

Sidenote: questo è compatibile con la memoria per una discreta quantità di caratteri per riga :) –