Repository 32bit  Forum
Repository 64bit  Wiki

QT4 & file di testo [RISOLTO]

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.

QT4 & file di testo [RISOLTO]

Messaggioda tgmx » mer mag 28, 2008 16:17

Ciao Ragazzi,

dovrei ricavare in QT4 il numero di righe in un file di testo mooooolto grande. La prima soluzione adottata era la seguente:
Codice: Seleziona tutto
if (!file.open(QFile::ReadOnly | QFile::Text))
{
   return;
}
QTextStream stream(&file);
//calcolo quante righe ci sono nel file:
int num_righe=0;
while(!stream.readLine().isNull())
{
   num_righe++;
}

ma dato che il file, come ho detto, è molto grande ci mette troppo a fare questo while.

Tra l'altro ho visto che da console è possibile ottenere questo valore molto velocemente:
Codice: Seleziona tutto
wc -l file.txt


Sapete consigliarmi un modo veloce per avere questo valore senza richiamare ws da programma e possibilmente usando funzioni di libreria delle QT4 ? :)

Grazie.
Ultima modifica di tgmx il ven mag 30, 2008 10:50, modificato 1 volta in totale.
Avatar utente
tgmx
Linux 3.x
Linux 3.x
 
Messaggi: 1330
Iscritto il: ven apr 28, 2006 13:40
Località: Ancona
Slackware: 13.37
Desktop: KDE 4

Re: QT4 & file di testo

Messaggioda mcosta » mer mag 28, 2008 19:24

Se ti interessa il solo numero di righe io farei così

Codice: Seleziona tutto
int linesCount(const QString& _fileName)
{
    QFile file(_fileName);

    if(!file.open(QFile::ReadOnly))
        return 0;

    int lines = 0;
    char ch;
    while(!file.atEnd())
    {
        file.getChar(&ch);
#ifdef Q_WS_MAC
        if(ch == '\r')  // Su MacOS il fine linea è '\r'
#else
        if(ch == '\n')
#endif
            break;

        ++lines;
    }
    return lines;
}
Avatar utente
mcosta
Linux 1.0
Linux 1.0
 
Messaggi: 54
Iscritto il: lun giu 14, 2004 23:00
Località: Marano (NA)
Nome Cognome: Massimo Costa
Slackware: 13.0
Kernel: 2.6.29.6
Desktop: KDE 4.2.4

Re: QT4 & file di testo

Messaggioda tgmx » mer mag 28, 2008 22:07

Effettivamente non è male come idea, domani la provo, credo però ci sia un errore:
Codice: Seleziona tutto
while(!file.atEnd())
    {
        file.getChar(&ch);
        if(ch == '\n')
            break;
        ++lines;
    }


in questo modo all'arrivo del fine linea esco dal while, immagino intendessi:
Codice: Seleziona tutto
while(!file.atEnd())
    {
        file.getChar(&ch);
        if(ch == '\n')
            ++lines;
    }


a parte questo dettaglio credo che la tua soluzione sia più veloce di quella che ho postato all'inizio, domani ti faccio sapere.

Grazie. :)
Avatar utente
tgmx
Linux 3.x
Linux 3.x
 
Messaggi: 1330
Iscritto il: ven apr 28, 2006 13:40
Località: Ancona
Slackware: 13.37
Desktop: KDE 4

Re: QT4 & file di testo

Messaggioda tgmx » gio mag 29, 2008 8:53

Ho provato la nuova soluzione e un po' migliora ma resta comunque molto più lenta del comando "wc -l file.txt"... :?

Eppure ho visto i sorgenti del comando "wc" e per calcolare il numero delle righe usa proprio il metodo che mi ha consigliato mcosta:
http://www.gnu.org/software/cflow/manua ... mmand.html

A cosa puù essere dovuta questa differenza di comportamente? Possibile sia solo il fatto che wc e in C mentre io uso quella parte di codice in C++ ?
Avatar utente
tgmx
Linux 3.x
Linux 3.x
 
Messaggi: 1330
Iscritto il: ven apr 28, 2006 13:40
Località: Ancona
Slackware: 13.37
Desktop: KDE 4

Re: QT4 & file di testo

Messaggioda mcosta » gio mag 29, 2008 10:24

Mi scuso per l'erroraccio nel codice proposto :? :? :?

Comunque la differenza di velocità rispetto a "wc" potrebbe essere dovuta al fatto che la classe QFile delle Qt esegua una serie di controlli per garantire l'accesso "protetto" al file.
Se ti interessa la velocità pura probabilmente ti conviene utilizzare le primitive base (non credo che la classe fstream del C++ sia molto più lenta delle primitive C).
Avatar utente
mcosta
Linux 1.0
Linux 1.0
 
Messaggi: 54
Iscritto il: lun giu 14, 2004 23:00
Località: Marano (NA)
Nome Cognome: Massimo Costa
Slackware: 13.0
Kernel: 2.6.29.6
Desktop: KDE 4.2.4

Re: QT4 & file di testo

Messaggioda tgmx » gio mag 29, 2008 10:41

mcosta ha scritto:Mi scuso per l'erroraccio nel codice proposto :? :? :?

Comunque la differenza di velocità rispetto a "wc" potrebbe essere dovuta al fatto che la classe QFile delle Qt esegua una serie di controlli per garantire l'accesso "protetto" al file.
Se ti interessa la velocità pura probabilmente ti conviene utilizzare le primitive base (non credo che la classe fstream del C++ sia molto più lenta delle primitive C).


Ora ho anche provato ad inserire nel mio codice la parte di "wc" che esegue l'operazione di conto:
Codice: Seleziona tutto
FILE *fp = fopen (fileName.toAscii(), "r");
         if (!fp)
            return;
         char ch;
         while ((ch = getc (fp)) != EOF)
         {
            if ((ch) == '\n')
               num_righe++;
         }
         fclose(fp);


ma non ho notato grandi miglioramenti... o mi sfugge qualcosa o magari wc è compilato con qualche particolare ottimizzazione... :?

Per adesso mi trovo costretto ad utilizzare QProcess:
Codice: Seleziona tutto
QProcess proc;
         proc.start("wc -l "+fileName);
         if(proc.waitForFinished(30000))   //se è terminato correttamente e nel tempo stabilito
         {
            QString str(proc.readAllStandardOutput());
            num_righe = str.split(" ")[0].toInt();
         }

in questo modo è una "scheggia" ma mi gioco la portabilità su windows... :cry:

In attesa di un'illuminazione mi trovo costretto ad usare questo altrimenti il programma ci mette più di un minuto.
Avatar utente
tgmx
Linux 3.x
Linux 3.x
 
Messaggi: 1330
Iscritto il: ven apr 28, 2006 13:40
Località: Ancona
Slackware: 13.37
Desktop: KDE 4

Re: QT4 & file di testo

Messaggioda alessiodf » gio mag 29, 2008 23:25

prova a bufferizzare un po che rendi tutto velocissimo.. ti costa un po di piu' in memoria pero'
QByteArray QIODevice::read ( qint64 maxSize ) ad esempio con questa.. potresti leggere blocchi di file di tipo umm 10k (solitamente non si va sopra i 4k per portabilita' su sistemi micro tipo una calcolatrice .) e su sti 10k (che stanno in memoria) potresti contare quanti \r o \r\n vi sono :)

questa e' una lettura non carattere per carattere, ma bufferizzata. e' piu' performante perche' il file viene mappato in memoria centrale con spezzoni piu' grandi.

nessuno ti vieta di caricare un file enorme (100mega) in memoria in un colpo solo :>
Avatar utente
alessiodf
Linux 2.6
Linux 2.6
 
Messaggi: 823
Iscritto il: ven ott 14, 2005 20:04
Località: Roma
Slackware: current
Kernel: 2.6.26.4
Desktop: Kde 4.1

Re: QT4 & file di testo

Messaggioda tgmx » ven mag 30, 2008 7:31

alessiodf ha scritto:prova a bufferizzare un po che rendi tutto velocissimo.. ti costa un po di piu' in memoria pero'
QByteArray QIODevice::read ( qint64 maxSize ) ad esempio con questa.. potresti leggere blocchi di file di tipo umm 10k (solitamente non si va sopra i 4k per portabilita' su sistemi micro tipo una calcolatrice .) e su sti 10k (che stanno in memoria) potresti contare quanti \r o \r\n vi sono :)

questa e' una lettura non carattere per carattere, ma bufferizzata. e' piu' performante perche' il file viene mappato in memoria centrale con spezzoni piu' grandi.

nessuno ti vieta di caricare un file enorme (100mega) in memoria in un colpo solo :>


Ora provo, però non è possibile caricare tutto in memoria dato che il file è da più di 500MB :roll: .

Continuo però a non caqpire come fa "wc" ad essere così veloce....
Avatar utente
tgmx
Linux 3.x
Linux 3.x
 
Messaggi: 1330
Iscritto il: ven apr 28, 2006 13:40
Località: Ancona
Slackware: 13.37
Desktop: KDE 4

Re: QT4 & file di testo

Messaggioda alessiodf » ven mag 30, 2008 8:53

500 mega? umm.. allora io leggerei a pezzi di addirittura 100k :) comunque, basta fare un po di prove..
Avatar utente
alessiodf
Linux 2.6
Linux 2.6
 
Messaggi: 823
Iscritto il: ven ott 14, 2005 20:04
Località: Roma
Slackware: current
Kernel: 2.6.26.4
Desktop: Kde 4.1

Re: QT4 & file di testo

Messaggioda tgmx » ven mag 30, 2008 10:49

alessiodf ha scritto:500 mega? umm.. allora io leggerei a pezzi di addirittura 100k :) comunque, basta fare un po di prove..


Alla fine questo è ciò che ho fatto:
Codice: Seleziona tutto
QByteArray lettura;
while(!(lettura=file.read(500*1024)).isEmpty())
         {
            QApplication::processEvents();
            for(int i=0; i<lettura.size(); i++)
            {
               if(lettura.at(i)=='\n')
                  num_righe++;
            }
         }


in questo modo la velocità di scansione del file si avvicina molto a quella di "wc" quindi non posso che ritenermi soddisfatto.... :D

Ho provato ad alzare utleriormente la quantità di byte bufferizzata ma non sembra migliorare quindi mi sono fermato a 500K.

Grazie mille del consiglio :) .

PS. Per completezza, ammesso che interessi a qualcuno :D , descrivo un po' meglio cosa fa questa piccola applicazione così magari può essere utile a qualcun'altro:
il programma ha lo scopo di caricare su un db mysql dei dati che si trovano in un file di testo sotto forma di stringhe di lunghezza fissa. Il fatto è che essendo un file molto grande questa operazione richiede del tempo così ho pensato di visualizzare a video una piccola barra di scorrimento. La barra di scorrimento però va inizializzata (giustamente) con un valore minimo e massimo in modo che lo scorrimento percentuale sia fedele allo stato dell'operazione in corso. In conclusione mi serviva sapere il numero di righe nel file prima di iniziare a caricarle nel db... :)
Avatar utente
tgmx
Linux 3.x
Linux 3.x
 
Messaggi: 1330
Iscritto il: ven apr 28, 2006 13:40
Località: Ancona
Slackware: 13.37
Desktop: KDE 4

Re: QT4 & file di testo [RISOLTO]

Messaggioda alessiodf » ven mag 30, 2008 11:43

int QByteArray::count ( char ch ) const

con questa, risparmi un ciclo.. e credo che se lo fai fa a qt, e' sicuramente piu' performante! quindi passagli '\n' ad esempio e prova ad aumentare il buffer size :D

edit: qt 4.4 fa questo per contare i caratteri in un qbyte array:
Codice: Seleziona tutto
int QByteArray::count(char ch) const
{
    int num = 0;
    const char *i = d->data + d->size;
    const char *b = d->data;
    while (i != b)
        if (*--i == ch)
            ++num;
    return num;
}
:thumbright:
Avatar utente
alessiodf
Linux 2.6
Linux 2.6
 
Messaggi: 823
Iscritto il: ven ott 14, 2005 20:04
Località: Roma
Slackware: current
Kernel: 2.6.26.4
Desktop: Kde 4.1

Re: QT4 & file di testo [RISOLTO]

Messaggioda tgmx » ven mag 30, 2008 13:08

alessiodf ha scritto:int QByteArray::count ( char ch ) const

con questa, risparmi un ciclo.. e credo che se lo fai fa a qt, e' sicuramente piu' performante! quindi passagli '\n' ad esempio e prova ad aumentare il buffer size :D

edit: qt 4.4 fa questo per contare i caratteri in un qbyte array:
Codice: Seleziona tutto
int QByteArray::count(char ch) const
{
    int num = 0;
    const char *i = d->data + d->size;
    const char *b = d->data;
    while (i != b)
        if (*--i == ch)
            ++num;
    return num;
}
:thumbright:


QByteArray::count mi era sfuggito... l'ho appena provata e forse guadagno mezzo secondo ma a parte la velocità resta comunque più pulito il codice del programma... :)

Se adesso troviamo un metodo di QFile che conta da solo le righe di un file di testo.... :D
Avatar utente
tgmx
Linux 3.x
Linux 3.x
 
Messaggi: 1330
Iscritto il: ven apr 28, 2006 13:40
Località: Ancona
Slackware: 13.37
Desktop: KDE 4

Re: QT4 & file di testo [RISOLTO]

Messaggioda mcosta » ven mag 30, 2008 16:22

Se adesso troviamo un metodo di QFile che conta da solo le righe di un file di testo.... :D


Ma allora dillo che non hai voglia di lavorare :D :D

Comunque butto lì una soluzione moooooolto "grezza"
Visto che ogni stringa ha lunghezza fissa potresti fare così

Codice: Seleziona tutto
const int LINE_SIZE = 100; // esempio 100 caratteri

QFile file(nomeFile);

int linesCount = file.size() / (LINE_SIZE + 1); // il +1 e' per considerare il ritorno a capo
Avatar utente
mcosta
Linux 1.0
Linux 1.0
 
Messaggi: 54
Iscritto il: lun giu 14, 2004 23:00
Località: Marano (NA)
Nome Cognome: Massimo Costa
Slackware: 13.0
Kernel: 2.6.29.6
Desktop: KDE 4.2.4

Re: QT4 & file di testo [RISOLTO]

Messaggioda tgmx » ven mag 30, 2008 16:34

mcosta ha scritto:Ma allora dillo che non hai voglia di lavorare :D :D


Se avevo voglia di lavorare non mi appassionavo all'informatica... :lol: :lol:

Comunque la tua soluzione non è adatta al mio scopo per il fatto che non ho la garanzia assoluta che le righe siano tutte della stessa lunghezza anche se è molto probabile. Perferisco qualcosa di preciso. :)
Avatar utente
tgmx
Linux 3.x
Linux 3.x
 
Messaggi: 1330
Iscritto il: ven apr 28, 2006 13:40
Località: Ancona
Slackware: 13.37
Desktop: KDE 4


Torna a Programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 5 ospiti