 | |
Il progetto dsy.it è l'unofficial support site dei corsi di laurea del Dipartimento di Scienze dell'Informazione e del Dipartimento di Informatica e Comunicazione della Statale di Milano. E' un servizio degli studenti per gli studenti, curato in modo no-profit da un gruppo di essi. I nostri servizi comprendono aree di discussione per ogni Corso di Laurea, un'area download per lo scambio file, una raccolta di link e un motore di ricerca, il supporto agli studenti lavoratori, il forum hosting per Professori e studenti, i blog, e molto altro...
In questa sezione è indicizzato in textonly il contenuto del nostro forum |
[Programmazione C] Problema di lettura di file video Clicca QUI per vedere il messaggio nel forum |
DarkGod |
Ciao, devo realizzare un programma in C che legga e successivamente modifichi dei file video che hanno una struttura simile al formato AVI.
Conosco la struttura interna del file, gli header e le informazioni che contiene, ma ho un problema quando tento di leggere i vari frame, infatti in molti casi la lettura di un frame si interrompe a metà e non riesco più a proseguire nella lettura del file.
Facendo varie prove ho capito che probabilmente il problema nasce dalla presenza di una sequenza di "zeri" all'interno del file, che viene interpretata dalla funzione read() come un carattere NULL, e quindi "fine del file". Il file però non è affatto terminato, ma se provo a fare altre read() mi viene restituito sempre 0.
Come posso leggere (e memorizare) il contenuto del file così com'è, senza che la lettura si blocchi a metà?
Grazie mille per qualsiasi aiuto... :) |
yeah |
Hai provato byte a byte con fgetc()? |
DeepBlue |
Oppure, se conosci le dimensioni del file, dovresti poter usare fread() (che fra l'altro è ANSI/POSIX compliant, al contrario della read()) |
DarkGod |
Originally posted by yeah
Hai provato byte a byte con fgetc()?
No... domani provo, grazie! :) |
DarkGod |
Originally posted by DeepBlue
Oppure, se conosci le dimensioni del file, dovresti poter usare fread() (che fra l'altro è ANSI/POSIX compliant, al contrario della read())
Perchè devo conoscere le dimensioni del file per usarla? |
yeah |
Mi sa che con l'idea di DeepBlue fai prima, puoi recuperare tutti i byte con una sola chiamata, invece che con n chiamate.
#include <stdio.h>
size_t fread(void *buffer, size_t size, size_t number, FILE *file);
Metti size a 1 e number alla dimensione del file e sei a posto :) |
DarkGod |
Originally posted by yeah
Mi sa che con l'idea di DeepBlue fai prima, puoi recuperare tutti i byte con una sola chiamata, invece che con n chiamate.
Metti size a 1 e number alla dimensione del file e sei a posto :)
Aspetta... ma così leggo tutto il file in una volta sola, giusto?
Io devo leggere i vari frame uno alla volta, perchè devo modificarli e sbatterli (ad uno ad uno) in un nuovo file che sto creando.
Leggendo tutto insieme, dopo dovrei scandire il buffer di memoria per trovare i vari frame... e mi servirebbe un buffer enorme, il filmato potrebbe essere di 100 MB per esempio. Leggendo invece un frame per volta posso allocare solo pochi KB... |
DeepBlue |
Originally posted by DarkGod
Aspetta... ma così leggo tutto il file in una volta sola, giusto?
Io devo leggere i vari frame uno alla volta, perchè devo modificarli e sbatterli (ad uno ad uno) in un nuovo file che sto creando.
Ok: tu sai quanto è grande un frame a priori? Se sì, allora puoi vedere un po' cosa riesci a combinare con fseek().
Se no, probabilmente visto che conosci le intestazioni dei frame, forse puoi calcolarne le dimensioni ed utilizzare fseek(). |
DarkGod |
Originally posted by DeepBlue
Ok: tu sai quanto è grande un frame a priori? Se sì, allora puoi vedere un po' cosa riesci a combinare con fseek().
Sì sì, la struttura dei frame la conosco perfettamente, campo per campo. Ogni frame ha un header che contiene anche la dimensione del frame stesso.
Il problema è che, per esempio, se ho un frame di 200 byte, faccendo:
read (file_descriptor, buffer, 200)
in alcuni frame invece di ritornarmi il valore 200, me ne ritorna uno minore. A questo punto, se faccio altre read per proseguire nella lettura, mi restituisce sempre e solo 0 (quindi non legge più nulla), come se il file fosse finito (ma ovviamente non lo è).
Da quello che ho capito, questo succede quando c'è una sequenza di zeri all'interno di un frame, che probabilmente viene interpretato dalla read() come un EOF.
Cmq, fseek() server per scorrere il puntatore in un file... ma in questo modo salto dei pezzi, no? |
yeah |
Aspetta... ma così leggo tutto il file in una volta sola, giusto?
Io devo leggere i vari frame uno alla volta, perchè devo modificarli e sbatterli (ad uno ad uno) in un nuovo file che sto creando.
In quel caso sì, ma se al posto della dimensione del file metti la dimensione del frame ti leggi solo il frame :) |
DarkGod |
Originally posted by yeah
In quel caso sì, ma se al posto della dimensione del file metti la dimensione del frame ti leggi solo il frame :)
Ma scusa... non è quello che sto già tentandio di fare? O__o
Oppure la fread() non si blocca come la read() ? |
yeah |
Scusa, deve essere l'ora :) e abbiamo anche postato contemporaneamente, non me ne ero accorto :)
Cmq non ho mai usato read(),però è strano che ti si 'blocchi'... in sè dovrebbe (come vedo dalle man pages) leggere un tot di byte, come la fread(), la differenza è che fread() fa parte della libreria standard del C, mentre read() è, come ha detto Deep, POSIX, quindi la sua disponibilità dipende dall'ambiente e dal compilatore.
Se vuoi prova con fread() o con fgetc(), ma secondo me il problema è un altro... mi sembra strano che si fermi per una sequenza di zeri... le man non dicono nulla a riguardo |
DarkGod |
Originally posted by yeah
Scusa, deve essere l'ora :) e abbiamo anche postato contemporaneamente, non me ne ero accorto :)
Come ti capisco... io ho pure la febbre e raffreddore, eh eh... :(
infatti mi sa che fra un attimo vado a nanna :)
Cmq non ho mai usato read(),però è strano che ti si 'blocchi'... in sè dovrebbe (come vedo dalle man pages) leggere un tot di byte, come la fread(), la differenza è che fread() fa parte della libreria standard del C, mentre read() è, come ha detto Deep, POSIX, quindi la sua disponibilità dipende dall'ambiente e dal compilatore.
Se vuoi prova con fread() o con fgetc(), ma secondo me il problema è un altro... mi sembra strano che si fermi per una sequenza di zeri... le man non dicono nulla
Sì, anche secondo me è strano, però i manuali dicono che la read restituisce meno byte di quanti ne dovrebbe leggere solo nel caso in cui abbia raggiunto la fine del file... Ma naturalmente un filmato di 60MB non può certo finire dopo il quarto frame! ;)
Eppure lì si blocca e non va più avanti. In ogni file si blocca in un punto diverso naturalmente.
Indagando un po' all'interno del file, ho notato che dove si blocca c'è una lunga sequenza di zeri... e dato che se non erro il carattere NULL è formato da zeri e identifica la fine di un file........ |
yeah |
e dato che se non erro il carattere NULL è formato da zeri e identifica la fine di un file........
No, in genere indica la fine delle stringhe ;)
Puoi postare del codice? Se trovo un avi provo a darci una occhiata |
DarkGod |
Originally posted by yeah
No, in genere indica la fine delle stringhe ;)
Puoi postare del codice? Se trovo un avi provo a darci una occhiata
Certo!
Ma ora non ho qui il codice... posto domani.
Ciauz! E grazie! :) |
DeepBlue |
Originally posted by DarkGod
Sì sì, la struttura dei frame la conosco perfettamente, campo per campo. Ogni frame ha un header che contiene anche la dimensione del frame stesso.
Il problema è che, per esempio, se ho un frame di 200 byte, faccendo:
read (file_descriptor, buffer, 200)
Scusa, non mi sono spiegato bene prima: al posto di read usa fread, che non dovrebbe soffrire degli stessi problemi della read.
Per quanto riguarda la read, potete leggere qui e qui
Cmq, fseek() server per scorrere il puntatore in un file... ma in questo modo salto dei pezzi, no?
Ti serve se hai la necesità di chiudere un file e riaprirlo iniziando a leggere da un punto ben preciso (il frame n). |
DarkGod |
Originally posted by yeah
[B]No, in genere indica la fine delle stringhe ;)
Cavolo, hai ragione, ho fatto confusione io!
Cmq se non è per la fine del file, perchè mai la read() si blocca?? O_o |
DarkGod |
Originally posted by DeepBlue
al posto di read usa fread, che non dovrebbe soffrire degli stessi problemi della read.
Ok, grazie, provo con la fread! :) |
DarkGod |
Originally posted by DeepBlue
Scusa, non mi sono spiegato bene prima: al posto di read usa fread, che non dovrebbe soffrire degli stessi problemi della read.
Per quanto riguarda la read, potete leggere qui e qui
Leggo dal primo link che mi hai indicato:
The return value is the number of bytes actually read. This might be less than size; for example, if there aren't that many bytes left in the file or if there aren't that many bytes immediately available. The exact behavior depends on what kind of file it is. Note that reading less than size bytes is not an error.
A value of zero indicates end-of-file (except if the value of the size argument is also zero). This is not considered an error. If you keep calling read while at end-of-file, it will keep returning zero and doing nothing else.
Questo è esattamente quello che capita a me: faccio diverse read(), leggo correttaente alcuni frame, poi, all'improvviso, una read() mi restituisce MENO byte di quelli che ho indicato, e facendo successive read() mi ritorna sempre il valore zero.
Secondo la documentazione, questo dovrebbe significare che ho raggiunto la fine del file, ma non è così. La lettura di un filmato mi si è bloccata al frame 4, mentre con un altro filmato addirittura al primo frame!
Notare cmq che non sono errori casuali, ma con ogni filmato si blocca sempre allo stesso punto. |
giulio |
Originally posted by DarkGod
Secondo la documentazione, questo dovrebbe significare che ho raggiunto la fine del file, ma non è così. La lettura di un filmato mi si è bloccata al frame 4, mentre con un altro filmato addirittura al primo frame!
Notare cmq che non sono errori casuali, ma con ogni filmato si blocca sempre allo stesso punto. [/B]
dunque:
dal manuale di read:
code:
NAME
read - read from a file descriptor
dal manuale di fread:
code:
NAME
fread, fwrite - binary stream input/output
La parola chiave e' binary , che compare nel manuale di fread.
Quindi devi usare quest'ultima, perche' read interpreta come eof eventuali byte con valore 0, peraltro totalmente legittimi anche nel bel mezzo di un file binario. |
DarkGod |
Per usare la fread() invece della read() devo aver aperto il file con una fopen()? Perchè la fread() vuole un puntatore al file, mentre la open() mi restituisce un file descriptor integer... |
giulio |
Originally posted by DarkGod
Per usare la fread() invece della read() devo aver aperto il file con una fopen()? Perchè la fread() vuole un puntatore al file, mentre la open() mi restituisce un file descriptor integer...
yep!
fopen, fread, fwrite e fclose al posto di open, read, write e close. |
DarkGod |
Prima di sostituire tutte le funzioni, ho provato a compilarlo sotto linux (più precisamente all'interno dell'ambiente "Cygwin", che emulla linux all'interno di windows) e lì la read() funziona perfettamente, non si blocca mai!
Da cosa può dipendere? Da una diversa codifica di EOF e NULL? |
DarkGod |
FUNZIONA!!!! :D:D:D
Utilizzando fread e fwrite (invece di read e write) in modalità binaria, il programma funziona sia sotto win che linux!
Grazie mille per i consigli... ;) |
|
|
|
|