Newsgroup: it.comp.lang.c++
Titolo: lettura file di testo leeeento

ciao a tutti,
premetto che sto iniziando ad imparare solo ora il c++ e che quindi la mia
domanda vi puň sembrare assurda o banale...
al momento lavoro con mingw sotto windows (quindi g++, versione 3.4.2) e sto
cercando di realizzare alcune funzioni portabili (in modo che possano girare
anche su linux, mac, etc) che leggano file di configurazione... quindi
prevalentemente file di testo...
ho fatto due esperimenti, mediante ifstream::getline e tramite
fopen/fgets... ma il risultato č sempre lo stesso... per leggere un file di
10000 righe ci mette 67 secondi!!
la mia funzione č strutturata in questo modo (ho tralasciato il contenuto
dei cicli semplicemente perchč ho commentato tutto anche io nel codice ed ho
la stessa lentezza!! sembrerebbe quasi come se le funzioni
pre-bufferizzassero il file (in maniera molto lenta) prima di passarlo alle
funzioni per la lettura):
versione con fgets --------------------------------------------------------
int yni_open (const string filename) {
 // da implementare
 // legge un file di testo e ne valorizza la mappa
 // torna 0 per ok, qualsiasi valore diverso da 0 per segnalare
 // problemi
 FILE *f;
 if ((f=fopen(filename.c_str(), "r")) == NULL) {
  cout << "Impossibile aprire il file " << filename << "\n";
  return -1;
 }
 char row[MAX_ROW_LENGTH];  // MAX_ROW_LENGTH = 4096
 string srow;
 int nrow = 0;
 while (fgets(row, sizeof(row), f)) {
    /* ...*/
  }
 fclose(f);
 cout << "fine lettura\n";
 return 0;
}
----------------------------------------------------------
versione con ifstream ------------------------------------
int yni_open (const string filename) {
 // da implementare
 // legge un file di testo e ne valorizza la mappa
 // torna 0 per ok, qualsiasi valore diverso da 0 per segnalare
 // problemi
 cout << "inizio lettura file\n";
 std::ifstream f (filename.c_str());
 if (!f) {
  cout << "Impossibile aprire il file " << filename << "\n";
  return -1;
 }
 cout << "file letto\n";
 char row[MAX_ROW_LENGTH];
 string srow;
 int nrow = 0;
 while (f) {
  f.getline (row, MAX_ROW_LENGTH);
  if (f) {
    /* ... */
  }
 }
 f.close();
 cout << "fine lettura\n";
 return 0;
}
----------------------------------------------------
non so piů che pensare e confido in voi per evitare di impazzire! ;)
vi saluto e vi ringrazio anticipatamente

Non e' che per caso all'interno del ciclo while hai messo qualche riga
di stampa (cout << "...";) perche' rallenta tantissimo il ciclo.
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 wrote in message
news:9f7056e6cd5e2637879...@mygate.mailgate.org...


La follia e' leggere il file per righe. Usa un buffer bello grande e
leggi a blocchi. Solo dopo, se ti serve, spezza il file in righe.
Ciao,
Nicola

mi sono documentato un pochino e ho fatto qualche prova "empirica"...
spostando, di fatto, il problema su un altro fronte...
andiamo con ordine...
qui vi segnalo un sito in cui è discusso un test comparativo tra le varie
modalità di lettura:
http://gcc.gnu.org/ml/gcc-bugs/2004-04/msg01484.html
queste, invece, sono le prove che ho compiuto io:
ho creato 3 file di testo rispettivamente con (1)25, (2)10.000, (3)200.000
righe ed ho provato il programmillo su diverse piattaforme con tutti e tre i
file...
--------
io sto sviluppando su un pc intel pentium 3 a 450 MHz, con 256 MB di ram,
S.O. Windows XP Professional, file system di tipo NTFS
per aprire il file (1) impiega 1 secondo circa, per il (2) ci mette tra i 65
e i 75 secondi... il terzo non ci ho provato nemmeno
---------
provato lo stesso eseguibile su un pc intel pentium 3 a 1 GHz, con 256 MB di
ram, S.O. Windows 2000 Professional, file system di tipo FAT32
per aprire il file (1) impiega pochi decimi, per il (2) ci mette 3 secondi,
per il (3) impiega 16 secondi (tempi a parer mio perfetti)
----------
provato lo stesso eseguibile su pc intel pentium a 180 MHz, con 64 MB di
ram, S.O. Windows ME, file system di tipo FAT32
per aprire il file (1) impiega 1 secondo circa, per il (2) ci mette 7
secondi, per il 3 occorrono 47 secondi (considerando che si tratta di uno
dei primissimi pentium... direi che non se la cava male)
----------
ricompilato lo stesso sorgente su un pc intel celeron a 700 MHz, con 64 MB
di ram, S.O: Linux Mandrake 10.0, file system di tipo jFS ext3
per aprire il file (1) impiega meno di un secondo, per il (2) ci mette 1
secondo, per il (3) impiega tra i 7 e i 10 secondi (considerando che stiamo
parlando di un celeron... non mi pare affatto male)
---------
a questo punto, la pietra dello scandalo sembrerebbe essere il NTFS di XP...
allora ho provato a mettere tutto su un cd (programma e dati - un
normalissimo 9660 con joliet - mode 1) e far girare tutto da lì...
a questo punto il file system diventa cdfs (anche su windows xp)... i
risultati sono pressochè identici (variano di 1 o 2 secondi al massimo)...
compreso su xp! ci mette i suoi 65-75 secondi sia lanciato da disco che da
cd... quindi il problema, più che essere NTFS sembrerebbe proprio essere XP!
ora la domanda che rimarrebbe da fare è... è un problema solo del mio xp o
di xp in generale? e qualora fosse di xp in generale... quale il modo per
mettervi una pezza?
spero che a qualcuno possa interessare tutta questa disquisizione e che
qualcuno abbia qualche idea o informazione... perchè io sto realmente
diventando matto ;)
ciao a tutti

 mettervi una pezza?
Se vuoi che lo provi sul mio mandami in privato programma in sorgente e
file da leggere.
EMG
--
EMAG Software Homepage:     
http://www.emagsoftware.it
The EMG's ZX-Spectrum Page: 
http://www.emagsoftware.it/spectrum
The Best of Spectrum Games: 
http://www.emagsoftware.it/tbosg

 file da leggere.
ti ho inviato programmillo cpp e file di test in privato e ti ringrazio fin
da ora...
per tutti gli altri mostro il sorgente "puntuale" qui:
8< ---------------------------------------------
#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
const int MAX_ROW_LENGTH = 4096;
int yni_open (const string filename) {
 FILE *f;
 if ((f=fopen(filename.c_str(), "r")) == NULL) {
  cout << "Impossibile aprire il file " << filename << "\n";
  return -1;
 }
 char row[MAX_ROW_LENGTH];
 while (fgets(row, MAX_ROW_LENGTH, f)) {
  /* ... fai qualcosa ... */
 }
 fclose(f);
 cout << "fine lettura\n";
 return 0;
}
int main(int argc, char* argv[]) {
 string filename = "test.yni";
 if (argc > 1) filename = argv[1];
 if (yni_open (filename) == 0) {
  cout << "fatto\n";
 } else {
  cout << "errore durante l'apertura del file yni\n";
 }
 return 0;
}
--------------------------------------------- >8
come ti dicevo, a beneficio di chi volesse continuare a seguire la vicenda
;)
se compilo il sorgente ed eseguo l'exe, la prima volta ci mette 67
secondi... la seconda volta che lancio l'eseguibile (senza ricompilare e con
gli stessi parametri) finisce istantaneamente (???
che fa? usa una qualche sorta di cache?)... se lo eseguo con parametri
diversi (facendolo ad esempio puntare ad altri file di testo)... a volte è
rapidissimo altre volte impiega un mare di tempo
inizio davvero a credere (e sperare) che i problemi stiano tutti sulla mia
macchina (o nella mia mente bacata... chissà)
ciao a tutti e intanto grazie

Allora gente,
grazie all'aiuto del gentilissimo Enrico Maria Giordano che ha provato il
mio programmillo direi di poter affermare con una certa sicurezza che il
problema è esclusivamente sulla mia macchina...
per questo mi scuso per essere andato OT per due volte (la prima perchè sono
caduto nell'implementazione sul solo windows xp anzichè rimanere sul
generale, la seconda è che di fatto il problema è un non problema reale!)
chiedo scusa a tutti... non me ne vogliate
ciao! ;)