PDA

Visualizza la versione completa : [C] Lettura/scrittura file binario


Slycarter
25-01-2009, 00:43
Salve a tutti,
volevo un aiuto si un programma che sto scrivendo per la manipolazione dei byte all'interno di un file (binario). In pratica leggo un file, modifico dei byte e lo riscrivo...una sorta di criptazione.

Spiego il problema in cui mi sono imbattuto e poi posto il codice.

Come vedrete nel codice, leggo il file ma quando stampo il contenuto dei byte memorizzati nel buffer i dati in output, che devono essere in esadecimale, non sono del tutto corretti.

In pratica, il ciclo di stampa Buf[i] sembra cominci a stampare non dall'inizio del buffer ma più avanti...si perde i primi byte. Se invece mietto Buf[0] o Buf[1] li stampa.

Poi mi stampa tutti i byte del file con "FFFFFF" davanti al byte interessato:

Posto il codice con la pseranza che qualcuno possa aitarmi. Grazie.


#include <stdio.h>
#include <stdlib.h>
#include <io.h>

int main (int argc, char *argv[])
{
FILE *pf;
char *Buf;
int i;
unsigned long fileLen;

if (argc!=2)
{
printf("Sintassi: nome_programma nome_file\n");
exit(1);
}
if ((pf=fopen(argv[1],"r+"))==NULL) {
printf("Impossibile aprire il file %s\n", argv[1]);
exit(1);
}

//Ricava lunghezza file
fseek(pf, 0, SEEK_END);
fileLen=ftell(pf);
fseek(pf, 0, SEEK_SET);

//Alloca memoria buffer
Buf=(char *)malloc(fileLen+1);
if (!Buf)
{
fprintf(stderr, "Memory error!");
fclose(pf);
exit(1);
}

//Lettura contenuto file nel buffer

while(!feof(pf)){
fread(Buf, fileLen, 1, pf);
}
fclose (pf);

for(i=0;i<=fileLen;i++)
printf("%.2x\n",(int)Buf[i]);

free(Buf);
}

YuYevon
25-01-2009, 10:02
Innanzitutto in modalità r+ non mi si apre alcun file binario. Ho sostituito con r (o rb) e funziona.

Poi, questo fatto



In pratica, il ciclo di stampa Buf[i] sembra cominci a stampare non dall'inizio del buffer ma più avanti...si perde i primi byte. Se invece mietto Buf[0] o Buf[1] li stampa.


mi sembra piuttosto strano: a me non succede... ovviamente - spero non sia questo il problema - se il file è molto lungo la shell non ti mostrerà mai tutti i byte dato che ha un buffer limitato... probabilmente ti mostrerà solo gli ultimi 100-200-300 (ma questo non perché il tuo programma non legge gli altri dal file). Per provare a vedere se ti stampa i primi byte, puoi provare a ciclare l'ultimo for da 0 a (ad esempio) 100, così sei sicuro che potrai leggere tutti i byte dalla shell (oppure li puoi stampare lo stesso tutti, ma su un file e non a video).

Per quanto riguarda il problema degli FFFFFF davanti a tutti i byte stampati (a dire il vero a me capita solo per alcuni e non per tutti) ho risolto il problema così:



char *Buf; -> unsigned char *Buf;


e ovviamente



Buf=(char *)malloc(fileLen+1); -> Buf=(unsigned char *)malloc(fileLen+1);


leggendo i byte come "unsigned char" piuttosto che come "char (signed)" sei sicuro che ognuno di essi ti verrà letto su 8 bit (secondo la codifica ASCII estesa, e non su 7 come prevede la codifica ASCII). Prova ad apportare questa modifica e facci sapere...

Per intenderci, a me questo programma funziona benissimo



#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
FILE *pf;
unsigned char *Buf;
int i;
unsigned long fileLen;

if (argc != 2) {
printf("Sintassi: nome_programma nome_file\n");
exit(1);
}
if ((pf = fopen(argv[1], "rb")) == NULL) {
printf("Impossibile aprire il file %s\n", argv[1]);
exit(1);
}
//Ricava lunghezza file
fseek(pf, 0, SEEK_END);
fileLen = ftell(pf);
fseek(pf, 0, SEEK_SET);

//Alloca memoria buffer
Buf = (unsigned char *) malloc(fileLen + 1);
if (!Buf) {
fprintf(stderr, "Memory error!");
fclose(pf);
exit(1);
}
//Lettura contenuto file nel buffer

while (!feof(pf)) {
fread(Buf, fileLen, 1, pf);
}
fclose(pf);

/* qui eventualmente sostituisci "fileLen" con 100 o 200 per vedere
se ti stampa i primi byte */
for (i = 0; i <= fileLen; i++)
printf("%.2x\n", (int) Buf[i]);

free(Buf);

return 0;
}

Samuele_70
25-01-2009, 10:45
Come ti ha detto YuYevon, apri il file in modalità "rb" (il "b" indica l'apertura in modalità binaria)
A cosa serve allocare un elemento in più per il buffer che rimarrà inutilizzato ?
di conseguenza il ciclo per la visualizzazione del bufer diventerà


for( i=0; i<fileLen; i++)
printf("%2X ", (int)Buf[i]);

Il ciclo while per la fread è perfettamente inutile.

Slycarter
25-01-2009, 23:27
Grazie per la risposta....ho fatto le modifiche suggerite e tutto funziona perfettamente.

Ora però sorge un altro problema: Dopo aver effettuato lo xor dei byte del buffer e vado a riscriverli nel file dal buffer con fwrite windws mi da errore dicendomi che si è tentato di leggere una locazione e la memoria non poteva essere written.

Sapete dirmi il perchè?

Questa è la parte di codice che ho aggiunto:

for(i=0;i<=fileLen;i++){
num=Buf[i];
num=num^key1;
Buf[i]=num;
i+=1;
num=Buf[i];
num=num^key2;
Buf[i]=num;
i+=1;
num=Buf[i];
num=num^key3;
Buf[i]=num;
}
fwrite(Buf, fileLen, 1, pf);
fclose(pf);
free(Buf);
}

oregon
25-01-2009, 23:46
Succede perche' all'interno del ciclo, quando i raggiunge il massimo valore (fileLen) tu incrementi la stessa i per ben 2 volte, puntando ad elementi che, evidentemente, non esistono ...

Slycarter
26-01-2009, 14:27
Originariamente inviato da oregon
Succede perche' all'interno del ciclo, quando i raggiunge il massimo valore (fileLen) tu incrementi la stessa i per ben 2 volte, puntando ad elementi che, evidentemente, non esistono ...


Quindi all'interno del ciclo for doveri mettere un ciclo if o do/while (esterno al for) che mi controlla il raggiungimento della fine del buffer?

oregon
26-01-2009, 14:34
No.

Dovresti terminare il ciclo for prima ...

Slycarter
26-01-2009, 14:44
Originariamente inviato da oregon
No.

Dovresti terminare il ciclo for prima ...


In che modo posso terminarlo prima scrivendo tutti gli elementi?

Puoi farmi un esempio?

oregon
26-01-2009, 14:57
Scusa, ma mi sembrava scontato ... la fine del ciclo la controlli con

i<=fileLen

devi modificare questo controllo tenendo conto che nel ciclo aumenti i due volte ...

Slycarter
26-01-2009, 19:19
Originariamente inviato da oregon
Scusa, ma mi sembrava scontato ... la fine del ciclo la controlli con

i<=fileLen

devi modificare questo controllo tenendo conto che nel ciclo aumenti i due volte ...


Ho risolto modificando la fine del ciclo come hai suggerito :

i>fileLen

ora l'errore non lo da più.

Terminato il ciclo e modificato tutti i byte del buffer devo riscriverli nello stesso file e lo faccio con l'istruzione

fwrite(Buf, fileLen, 1, pf);

ma a quanto pare non funziona...il file rimane invariato. La parte di sorgente interessata l'ho postat più sopra.

Come mai non lo modifica? Il file l'ho aperto in lettura/scrittura "r+b".

Grazie.

Loading