PDA

View Full Version : linguaggio C - Una mano per un semplice problema di lettura file - un aiuto?


Robbiez
27-06-2011, 13:57
Un ciao a tutta la popolazione di HArdware Upgrade.

Il mio problema è abbastanza semplice:

vorrei leggere un file dal primo all'ultimo byte, e inserire gli elementi letti in un vettore unidimensionale, così che ogni elemento del vettore sia un byte del file...ad esempio vorrei ottenere una cosa di questo tipo (sotto c'è l'inizio di un file jpeg preso da un tool apposito di lettura file, in cui i byte sono espressi in esadecimale)

int fileScansionato[]={0xFF,0xD8,0xFF,0xE0,0x00,0x10,0x4A,0x46,0x49,0x4 6,0x00,0x01,0x01,0x01......}

Ho letto molte guide sulla lettura/scrittura di file di testo o binari, senza trovare la soluzione!
utilizzando la funzione fread, o funzioni analoghe ho qualche problema, anche perchè non conosco la dimensione del file e quindi quella del vettore che devo creare!inoltre gli elementi del vettore risultano sballati, forse perchè a me interessano i byte "effettivi" del file...Ad esempio nel file jpeg che sto analizzando, il file è di 563 byte , ma l'occupazione su disco è di 4 KB...

Aggiungo che sono sotto mac os x e uso xcode come compilatore.


Sarei grato a chiunque voglia darmi una dritta...Sono nelle vostre mani!:mc:
Grazie e saluti!

tuccio`
27-06-2011, 14:21
se vuoi leggerlo tutto devi vedere prima quanto è grande, allocare un array abbastanza grande e leggere tutto con fread

però la libreria c non mi pare ti dia un modo per vedere la dimensione del file, quindi dovresti usare altri modi (ad esempio su mac os puoi usare la stat)

detto questo, fai prima mappando il file in memoria (su mac os puoi farlo con mmap (http://pubs.opengroup.org/onlinepubs/009695399/functions/mmap.html))

Robbiez
27-06-2011, 15:45
se vuoi leggerlo tutto devi vedere prima quanto è grande, allocare un array abbastanza grande e leggere tutto con fread

però la libreria c non mi pare ti dia un modo per vedere la dimensione del file, quindi dovresti usare altri modi (ad esempio su mac os puoi usare la stat)

detto questo, fai prima mappando il file in memoria (su mac os puoi farlo con mmap (http://pubs.opengroup.org/onlinepubs/009695399/functions/mmap.html))

Grazie per la risposta! però ho alcuni "ma"...:)

1)anche conoscendo la dimensione esatta del file in byte (leggendola dalle proprietà del file) gli elementi del vettore restituito sono costituiti da 4 byte e non da un byte come richiesto nella fread.

2)ottengo comunque dei valori "sballati": ad esempio se leggo i primi 10 elementi del file ottengo un risultato, e se leggo i primi 20 ne ottengo altri.

Per chiarezza posto il codice che ho usato:

#include <stdio.h>

int main (int argc, const char * argv[]) {

FILE *PuntFile;
int dimensione=563;
int dati[dimensione];
int kap;

PuntFile=fopen("sediciperSS.jpg","rb");


if(PuntFile==NULL)
printf("ERRORE NELL'APERTURA DEL FILE\n\n");
else
{
printf("\n\nFILE CARICATO CORRETTAMENTE");
kap=fread(dati,1,dimensione,PuntFile);
printf("\nNumero di valori effettivamente letti: %d\n",kap);

printf("vettore letto:\n");
for (int i=0;i<dimensione;i++){
printf("%x ",dati[i]);
}

}
fclose(PuntFile);
return 0;

}

Il risultato è che Kap (valori letti effettivamente) è zero....anche se di norma dovrebbe essere pari a dimensione (563), inoltre nella stampa del vettore dati, questo è errato....

Per quanto riguarda il discorso legato alla dimensione del file, penso che sia incredibile che non sia possibile con la libreria standard determinare la lunghezza del file...

Continuo a ringraziare chiunque per qualsiasi delucidazione...
Adesso do un occhiata a mmap per vedere se potrebbe aiutare in qualche modo

tuccio`
27-06-2011, 16:20
il problema allora è che la fread ti ritorna 0 e non riesce a leggere nessun byte, onestamente a guardare il codice non me lo saprei spiegare a dire il vero, c'è qualche motivo particolare per cui quel file non possa essere letto? (tipo, su mac os x, visto che non ne so niente, i lock sono mandatory? non è che il file è lockato da qualche programma? è strano onestamente che non riesca a leggerlo una volta aperto)

clockover
27-06-2011, 17:23
Prima di tutto con questo puoi risalire alla dimensione del file da leggere

FILE *f = fopen(...);
fseek(f, 0, SEEK_END);
long l = ftello(f);

inoltre con fread puoi avere i blocchi della dimensione che ritieni più opportuno dato che
fread(puntatore al buffer, dimensione del blocco, numero di blocchi da leggere, puntatore al file)

se tu metti fread(dati,1,dimensione,PuntFile);

è ovvio che viene tutto sballato perchè tu leggi 1 byte 563 volte e va bene, ma non va veramente bene perchè il tuo buffer dati si aspetta che 1 solo blocco valga 4 byte!

Quindi morale della favola cambia dati da tipo intero a char!

edit:
penso si capisca che "dati" è il tuo buffer

tuccio`
27-06-2011, 17:48
se tu metti fread(dati,1,dimensione,PuntFile);

è ovvio che viene tutto sballato perchè tu leggi 1 byte 563 volte e va bene, ma non va veramente bene perchè il tuo buffer dati si aspetta che 1 solo blocco valga 4 byte!se ha allocato un array di int da 563.. gli "avanzerà" e chiaramente è sballato nella stampa, e dovrebbe usare char o, meglio, unsigned char, però non è una giustificazione per il fatto che kap è uguale a 0 quando lo stampa

clockover
27-06-2011, 18:12
Be di sicuro c'è altro che non va...ad esempio che cosa vuol dire "rb" come secondo parametro della fopen? non mi risulta nessuna b dalla documentazione


poi sempre a Robbiez indenta il codice che ci aiuti ad aiutarti

tuccio`
27-06-2011, 18:51
b è binary

clockover
27-06-2011, 19:37
b è binary

a si ok l'ho trovato :D

Robbiez
28-06-2011, 15:24
grazie per le risposte!
DAvvero mille grazie!
Anzi 3E8 grazie (in esadecimale)a clockover e tucciò!:)

adesso analizzo bene bene quanto avete scritto....
Intanto posso fare un paio di considerazioni:

il codice postato era corretto,ovvero:
io utilizzo xcode, e in sostanza cambiando il tipo di progetto, funziona perfettamente....Sono passato da un progetto command line C ad un progetto Iphone...e il kap improvvisamente era corretto, così come la scansione del file(ho fatto il copia/incolla del mio codice) . Chissà il perchè...

Non sono comunque riuscito ad avere nel mio vettore dati, elementi da 1 byte, ma sempre da 4 byte, ma poco male perchè ho fatto una funzioncina che separa i singoli byte, sfruttando le proprietà del sistema numerico esadecimale
ad esempio a partire dall'elemento dell'array FFD81AF5, crea 4 elementi {FF,D8,1A,F5}...

Il problema resta per adesso solo quello di capire la dimensione del file...A tal proposito sto seguendo i vostri suggerimenti,
e sarei grato a chiunque abbia qualche altro suggerimento per cercare di estrarre in maniera semplice la dimensione, in byte, di un qualsiasi file (ovviamente sfruttando la libreria standard del c)

Ci lavoro un'altro po su..e vediamo che ne esce.:stordita: :stordita:

Grazie ancora:)

clockover
28-06-2011, 15:31
Il problema resta per adesso solo quello di capire la dimensione del file...

guarda che te l'ho scritto come ricavarti la dimensione del file :rolleyes:

Robbiez
28-06-2011, 15:40
guarda che te l'ho scritto come ricavarti la dimensione del file :rolleyes:

si si ho visto (ancora grazie), ci stavo proprio ora, lavorando su...

Robbiez
28-06-2011, 16:32
Ricapitolando, nel mio codice utilizzo prima

FILE *f = fopen(...);
fseek(f, 0, SEEK_END);
long l = ftello(f)

per valutare la dimensione del file.

In seguito però devo rifare fopen(...) prima di fare fread, altrimenti la fread non funziona, qualcuno sa spiegarmi il perchè?

clockover
28-06-2011, 16:37
perchè se fai fseek impostando SEEK_END vai alla fine del file...

dopo che ti sei trovato la dimensione del file dai rewind(filePointer);
che è del tutto equivalente a fseek(filePointer, 0, SEEK_SET)

Robbiez
28-06-2011, 17:20
perchè se fai fseek impostando SEEK_END vai alla fine del file...

dopo che ti sei trovato la dimensione del file dai rewind(filePointer);
che è del tutto equivalente a fseek(filePointer, 0, SEEK_SET)

Perfetto, capito perfettamente!

ti ringrazio tantissimo per l'aiuto,infinitamente!
e spero che questi post siano prima o poi di aiuto a qualcun'altro!