Newsgroup: it.comp.www.php
Titolo: fgets e lettura inversa

Ciao a tutti.
Il manuale insegna un semplice modo per leggere riga riga il contenuto
di un file, ne riporto il codice:
 $fd = fopen ("file.txt", "r");
  while (!feof ($fd)) {
    $buffer = fgets($fd, 4096);
    echo $buffer;
Fin qui tutto ok. E siccome la lettura di ciascuna riga avviene in senso
discendente, ne ricavo che in seguito a fgets() il puntatore viene
spostato verso il basso - appunto - di una riga. In pratica il codice
appena visto potremmo interpretarlo cosě:
finché (non viene raggiunta la eof) {
$buffer = restituzione dell'intera riga, INOLTRE 
fseek($fd, il punto dove eravamo PIU' tanti byte quanti ne contiene la
riga appena letta).
[se ho capito male correggetemi pure]
La domanda.
Se invece volessi leggere il file all'inverso (cioč, ancora riga riga,
ma dalla fine all'inizio), secondo voi č possibile?
Sarebbe semplice se certi dati fossero conosciuti, mi spiego:
fseek($fd, ?)
$buffer = fgets($fd, 4096);
fseek($fd, il punto dove eravamo MENO tanti byte quanti ne contiene la
riga appena letta MENO tanti byte quanti ne contiene la riga
precedente).
Viene spontaneo pensare a un file("file.txt") e un reverse dell'intero
array, ma si tratta di un metodo che non risponde alle mie esigenze
(evito di spiegarvene il perché, altrimenti non la finisco piů ^_^ ).
Io non ho idee, voi ne avete?
Grazie a tutti
-- 
Nicoletta

 Grazie a tutti
Se vuoi evitare l'uso degli array, dubito che ci possano essere valide 
alternative ...
personalmente non riesco a pensarne alcuna ...

 (evito di spiegarvene il perché, altrimenti non la finisco più ^_^ ).
Se devi leggere file di testo di dimensioni non eccessive*, potresti usare
questo trucco:
$fd = fopen ('file.txt', 'r');
$buffer = '';
while (!feof ($fd)) {
    $buffer = fgets($fd, 4096) . $buffer;
}
echo $buffer;
Ovvero copiare ogni nuovo blocco di testo _a sinistra_ del testo letto fino
a quel punto, e effettuare un echo (o utilizzare $buffer, secondo le tue
necessità) solo dopo aver raggiunto la fine del file.
LB
* dimensioni non eccessive poichè il file viene contenuto per intero in
memoria nella variabile buffer

 memoria nella variabile buffer
Proprio come avviene creando un array con la funzione file().
Il fatto è che quel documento lo sto usando come DB (non so e comunque
non potrei usare MySQL), ciononostante, dei numerosi record inseriti, ne
devo mostrare 5, 10, massimo 20, non di più (e sempre attigui). Ecco che
ho pensato a una soluzione del genere, che spreca pochissime risorse:
$arBuffer=array();
$fd = fopen ($file, "r");
fseek($fd,11516); // il numero su cui spostare il puntatore
                 //  mi è SEMPRE noto, quindi posso partire
                 //  dal punto che voglio
 for ($i=0;$i < 20; $i++) {
    if (!feof ($fd)) { // "freno" il push se raggiungo la eof
    array_push ($arBuffer,fgets($fd, 1024));
    }
 }
fclose ($fd);
/* a questo punto esibisco gli n record inseriti nell'array $arBuffer
formattati a dovere */
Se si tratta di "scendere" nella lettura, tutto questo non crea il
benché minimo problema*, ma come vedi ne crea molti "salendo".
* sperimentato su un file fittizio di 1.000.000 e passa righe: non fa
una grinza ed è velocissimo.
Se alla luce di quanto sopra vi viene in mente qualcosa ne sarei felice,
in caso contrario vi ringrazio comunque dell'interessamento, siete stati
gentilissimi.
Ciao :)
-- 
Nicoletta

 wrote:
|
[cut]
E se invece di fare una lettura al contrario non inserissi direttamente
i tuoi "record" nell'ordine inverso?
E' solo un'idea...
Ciao
-- 
..::[ Panz ]::..
-----------------------
per rispondere riscrivi in numeri la mia eMail!

 E' solo un'idea...
E io ti ringrazio di averla avuta ^_^
-- 
Nicoletta

 Io non ho idee, voi ne avete?
Ho appena scritto questa piccola funzione che stampa in ordine inverso
le righe del contenuto di un file (e' priva di controlli sul file 
e non ho fatto parecchi test!).
Usa una array per memorizzare la lunghezza di ogni riga del file,
bisgna valutare bene quindi la dimensione del file.
Magari puo suggerirti una soluzione.
<?php
function InverteRighe($file)
{
  $contenuto=array();
  $infoRighe=array();
  $numByte=filesize($file);
 
  $id=fopen($file,'r');
  while ( ($infoRighe[]=strlen(fgets($id))) );
  $infoRighe=array_reverse($infoRighe);
  fseek($id,0); $posRiga=0;
 
  foreach ($infoRighe as $lenRiga)
  {
   if (!$lenRiga) continue;
   $posRiga+=$lenRiga;
   fseek($id,$numByte-$posRiga);
   echo fgets($id).'<br>';
  }
}
InverteRighe('file.txt');
?> 
Simone Valenti

 ho pensato a una soluzione del genere, che spreca pochissime risorse:
Se lo vuoi veramente utilizzare come DB forse ti conviene utilizzare qualche
tecnica simile a quella dei DB, tipo usare record di dimensione fissa,
riempendoli in caso con un po' di spazi.
In questo modo hai un file che ha come dimensione NUM_RECORD * DIM_RECORD,
ed in un attimo sapresti dove spostarti per leggere gli ultimi cinque (che
poi ti inverti in php).
Es:
record di 100 byte l'uno
il file č di 4500 byte = 45 record
se vuoi leggere gli ultimi cinque devi puntare al byte
4500 - (5 * 100)
Se non vuoi utilizzare record di dimensione fissa potresti leggere gli
ultimi X byte del file, metterteli in un array, ordinarteli e leggere quelli
che ti servono. Il trucco č quindi nella scelta di questo X, che potresti
perň calcolare come la dimensione massima possibile per un record * num di
record che ti servono:
Es: record di dimensione massima 150 byte (anche se in genere sono da 30
byte)
file di dimensione 465432675432 byte =)
per leggere gli ultimi 5 record parti da
465432675432 - (5*150)
Avrai in genere record che non ti servono, ma almeno limiti i danni
NB: in entrambi i casi ricordati che l'accapo ti prende uno o due byte!
Ludovico Grossi

> Io non ho idee, voi ne avete?
se usi hosting linux, ti č permesso usare shell_exec e l'utente che usa
apache puņ usare tail (di solito si) puoi fare questo: prendi le ultime 5
righe del file o quelle che ti servono, le esplodi in un array e lo giri, in
questo modo hai quello che ti serve. In una riga..
$testo=array_reverse( explode("\n", shell_exec("tail --lines=5
file_di_testo.txt"),6));


Salve,
questo dovrebbe andare al caso tuo...
 $fp = fopen('myfile', 'r');
 while (!feof ($fp)) {
 $rows[] = fgets($fp);
 }
 fclose($fp);
 echo '<pre>';
 echo ($ord == 'diretto') ? join('', $rows) : join('',
array_reverse($rows));
 echo '</pre>'
Saluti
Corrado Modica
www.pachinoglobale.com

 gentilissimi.
Proprio oggi la mail (quasi) giornaliera di PhpClasses mi informa di un
semplice motore SQL basato su file, pDB
(
http://www.phpclasses.org/browse/package/1672.html
): ora non so se possa
soddisfare i tuoi requisiti o se risulti sovradimensionato, ma vedi se ti
puň interessare, dato che non puoi utilizzare MySQL o altri DB.
Saluti
LB

Mi rivolgo a tutti coloro che hanno partecipato al thread.
Sono stupefatta e direi (ma sì, concedetemelo, ho la lacrimuccia facile)
commossa dalla vostra attenzione e gentilezza. 
Quello che chiedevo erano idee, e ne ho avute molte di più di quanto non
mi aspettassi. Ora ho materiale su cui studiare, su cui riflettere, su
cui passare in bianco le prossime notti ^_^
 
Mi ci vorrà del tempo, ma dopo un'attenta lettura dei vostri interventi
intuisco che l'obiettivo può essere raggiunto.
Grazie davvero, grazie di cuore.
-- 
Nicoletta

 Grazie davvero, grazie di cuore.
Prego, il newsgroup esiste per questo :)
LB