Newsgroup: it.comp.lang.c
Titolo: velocizzare la scrittura del file

ciao a tutti,
      ho un problema:
dopo aver letto TOT blocchi da 256 byte di un file con fread(....),
e elaborati opportunamente vorrei scriverli in un file con fwrite(...).
Ora quando scrivo singolarmente ogni blocco da 256 byte sul file di 
uscita, ottengo il risultato voluto, cioe' il file con i dati corretti.
Vorrei invece cercare di allocare TOT pacchetti da 256 byte, in memoria 
e POI scrivere tutto sul file, riempire altri TOT pacchetti in memoria e 
scrivere sul file,
non voglio insomma scrivere ogni blocco singolarmente ma a gruppi.
Ho scritto un ciclo do while per leggere, elaborare, caricare sul 
buffer, e scrivere su file, ogni blocco da 256 byte.
Ecco la mia interpretazione dopo la fopen per i file sorgente e 
destinazione:
#define MAX_BUFFER 1024
#define BLOCK_LEN  256
...
unsigned char buffer[MAX_BUFFER*BLOCK_LEN];
fopen(......
fopen(...
...
memset(buffer,'\0',MAX_BUFFER*TS_LEN); // Pulizia buffer
do {
     fread( block, sizeof(block), 1, mysourcefile );
     elaborazione(block);
     if (block_pack == MAX_BUFFER-1) {	//Controllo buffer pieno
         fwrite( buffer, sizeof(buffer), 1, mydestfile );
	block_pack = 0;         //reset contatore posizione buffer
     	memset(buffer,'\0',MAX_BUFFER*BLOCK_LEN);	//pulizia buffer
     	fflush(mydestfile); 		//scrittura forzata (e' giusto?)
     }
     else
       memcpy( buffer+block_pack*BLOCK_LEN, block, BLOCK_LEN);
     block_pack++;
} while ( !feof( mydestfile ) ) ;
fclose(...
fclose(...
-----------------------------------------------
il codice mi funziona, ma non ottengo il file corretto, sia in 
dimensione che di contenuto.
Dove sta l'errore?
Eppure dovrebbe essere cosi'.
Per file molto grossi, tipo 900 mega, il PC impiega una vita per 
scrivere singolarmente ogni blocco da 256 bytes, sul file di destinazione.
Ecco perche' vorrei implementare un buffer.
Su Windows, noto che premendo sulla finestra cartelle F5, non mi si 
aggiorna la dimensione del file che sto elaborando, mentre con altri 
programmi che fanno la stessa cosa, vedo scorrere la dimensione che 
viene incrementata di tanto in tanto.
E' possibile ottenere questo in C, ovvero evitare che il file sia 
praticamente sempre a 0 bytes anche se il programma sta effettivamente 
scrivendo sul disco, finche' il programma non finisce la scrittura??
l'esempio lampante si ha quando si convertono le BIN dei CD, in ISO, il 
file con il passare dell'elaborazione non rimane FISSO a 0 byte.
Saluti,
       TorbaX.
-- 
--------------------------------------
Info SkyStar2 for Linux(forum):
http://www.assitecforum.com
 section "SkyStar2 DVB Sky4Linux Project)
:-)

 scrivendo sul disco, finche' il programma non finisce la scrittura??
Non penso sia un problema del C ma del sistema operativo che tu usi
infatti in hai detto che usi winzozz, su linux se effetivamente
il tuo programma scrive su un file diversi blocchi per volta
tramite il comando ls -l (digitato più volte in modo da emulare un refresh)
puoi effetivamente vedere che la dimensione del file che aumenta
Ciao Max
-----------------------------------------------------------
 Secondo alcuni autorevoli testi di tecnica Aeronautica,
 il calabrone non può volare, a causa della forma e del
 peso del proprio corpo in rapporto alla superficie alare. 
 Ma il calabrone non lo sa e perciò continua a volare.
					     Igor Sikorsky
-----------------------------------------------------------

Max wrote:

si anch'io ho provato "ls -l", tanto per vedere a che punto e' un file 
in scrittura, su Linux.
su Windows, il comportamento e' diverso, certe volte  il file e' 
stabilmente a ZERO bytes, magari in altri programmi, noto che il file si 
"autoincrementa" aggiornando la propria dimensione.
Non so ancora spiegarmelo.
e poi voglio evitare che FINCHE' il programma sta scrivendo nel file, in 
append mode, la dimensione ESSENDO FISSA a zero bytes, resti tale anche 
se il mio PC fa un bel crash, perdendo tutta l'elaborazione, dato che 
non c'e' scritto da nessuna parte che il file e' diverso da ZERO bytes.
-- 
--------------------------------------
Info *SkyStar2* for Linux(forum):


 il file con il passare dell'elaborazione non rimane FISSO a 0 byte.
Probabilmente il problema sta nel fatto che il file e' aperto (con
fopen) in esclusiva.
Prova a riscrivere il programma usando CreateFile e WriteFile.
-- 
-=[]=---iAN CooG---=[]=-
* Intel Pentium: random inside! (tm)

TorbaX wrote:
[...]
 > Per file molto grossi, tipo 900 mega, il PC impiega una vita per
 > scrivere singolarmente ogni blocco da 256 bytes, sul file di
 > destinazione.
[...]
Scusa, ma perche' leggere a blocchi di 256 bytes?
Soprattutto, perche' bufferizzare n letture da 256 bytes e spararle giu' 
tutte contemporaneamente?
Con Windows io ho notato che leggere i file a blocchi di 1Mbyte e' molto 
piu' veloce (sfrutti di piu' la cache) se lavori su dischi locali (in 
caso di accessi via rete o da floppy questo valore va ovviamente ridotto 
per via delle velocita' di trasferimento minori). Con buffer di maggiori 
dimensioni si iniziano a notare rallentamenti per via della velocita' 
trasferimento dei dati.
In piu', se la scrittura non e' critica (non ti serve essere sicuro che 
i dati siano scritti effettivamente su disco in caso di spegnimento 
brutale del sistema o crash) togli la flush o al limite mettila solo 
alla chiusura del file.
Cosi' senza usare procedure che bufferizzano i dati, utilizzi un solo 
buffer e sfrutti la cache del sistema per velocizzare ulteriormente la 
scrittura.
Luca Pascali


Ciao,
Nids


 Eppure dovrebbe essere cosi'.
c'ho preso? :)
-- 
mattia
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG


grazie del consiglio,  sono riuscito a sistemare il problema,
ecco la mia versione del BUFFER...
tralascio le righe e controlli inutili e ovvii:
#define MAX_BUFFER 1024
#define BLOCK_LEN  256
...
...
...
tsfile = fopen(src_filename,"rb")
dest_file = fopen(dest_filename,"wb")
...
...
...
	memset(buffer,'\0',MAX_BUFFER*BLOCK_LEN); // Pulizia buffer
long numero_p = 0;
int freebuffer = 1;	//check residuo buffer dopo fine file
do {
    fread(tsp, sizeof(tsp), 1, tsfile );	//Lettura pacchetto
    elaborazione(tsp);        //Elaborazione
 
    numero_p++;
    if (!(numero_p % 150000)) {    //controllo per forzare 
l'aggiornamento della dimensione del file, ogni TOT pacchetti
       fclose(dest_tsfile);	
       dest_file = fopen(dest_filename,"ab"); // modo append
    }
         if (block_pack == MAX_BUFFER) {    //Controllo buffer pieno
             fwrite( buffer, (block_pack)*TS_LEN, 1, dest_file );
         	block_pack = 0;         //reset contatore posizione buffer
         	freebuffer = 1;
          	fflush(dest_file);         //scrittura forzata ?????
          	memset(buffer,'\0',MAX_BUFFER*BLOCK_LEN); // Pulizia buffer
        	}
        	else {
              	memcpy( buffer+block_pack*BLOCK_LEN, tsp, BLOCK_LEN);
        	       	block_pack++;
        	       	freebuffer = 0;
        	}
     } while ( !feof( src_file ) );
     if (freebuffer == 0) //scrittura del buffer residuo su file
     	fwrite(buffer,sizeof(buffer),1,dest_file);
..
...
fclose....
fclose....
----------------
Ora ho risolto il problema,
avevo poi il problema della memoria che non bastava al sistema per 
"elaborare" i dati.... beh' a causa di una malloc inutile, ogni volta 
che leggevo un pacchetto, la memoria utilizzata dal programma, aumentava 
a dismisura, fino a che il programma, andava in crash.
anche quello problema risolto. Ho sostituito la creazione dinamica 
tramite malloc si un array (utilizzato sempre con la stessa dimensione), 
con una dichiarazione: char array[DIM]; e utilizzando memset e memcpy, 
per resettare a zero ogni contenuto, e per copiare blochi di memoria su 
tale array.
Anche quello problema risolto.:-)
Con un po'di pazienza si riesce ad ottenere sempre qualcosa.
