PDA

Visualizza la versione completa : [C++] Scrittura file binario


Luciano79
11-06-2009, 17:21
bel rompicapo...

ho un programma che tra le varie operazioni accoda 2 file binari in un file di output.
Il file di output è esattamente della dimensione che mi aspettavo (ovvero la somma dei due file di input esclusi alcune parti da eliminare). Di fatto quindi il file di output dovrebbe essere composto da una prima parte che contiene il primo file di input e da una seconda parte che contiene il secondo file di input. La prima parte è corretta (contiene il primo file di input) la seconda parte, pur essendo della dimensione del secondo file di input, è errata perchè contiene sempre lo stesso carattere (in esadecimale "CD"). La cosa strana è che, per cercare di capire dove possa essere l'errore, a video stampo tramite "printf" il contenuto della variabile che vado a scrivere nel file e la vedo correttamente!!!
Riporto le parti del codice che possono interessare:


FILE *fpi, *fpo;
char *BufferRecord;
...
fpo=fopen(NomeFileOutput,"wb");
for(ContatoreFile=0;ContatoreFile<NumeroDiFile;ContatoreFile++)
{
...
fpi=fopen(NomeFileInput,"rb");
while(get_filesize(ElencoFileInput[ContatoreFile])<ByteLetti)
{
....
fwrite(BufferRecord,LenRecord+1,1,fpo);
printf("%c",BufferRecord[0]); //stampo a video il primo carattere del record e lo vedo correttamente!!!
}
fclose(fpi);
}
fcloseall();



in debug visualizzo la variabile BufferRecord prima di essere scritta e la vedo correttamente...
:berto:

oregon
11-06-2009, 17:43
Mah ... dal codice che hai mostrato non si puo' capire dove sia l'errore ...

In particolare, cosa fa la funzione get_filesize in

while(get_filesize(ElencoFileInput[ContatoreFile])<ByteLetti

?

Quando e come leggi (sarà durante i ... ) ?

Perche' scrivi la quantità di byte

LenRecord+1

(ovvero perche' +1 ?)

Luciano79
11-06-2009, 18:11
Originariamente inviato da oregon
Mah ... dal codice che hai mostrato non si puo' capire dove sia l'errore ...

In particolare, cosa fa la funzione get_filesize in

while(get_filesize(ElencoFileInput[ContatoreFile])<ByteLetti

?

Quando e come leggi (sarà durante i ... ) ?

Perche' scrivi la quantità di byte

LenRecord+1

(ovvero perche' +1 ?)

- get_filesize ottiene la dimensione del file. Esco dal ciclo quando ho letto tutti i byte. Questo perchè leggo a blocchi variabili e non riesco ad intercettare in anticipo l'eof.
- leggo in punti diversi duranti i ...
- il +1 è perchè la variabile LenRecord la calcolo come se partisse da zero (non da uno). E' una cosa che per correttezza devo sistemarlo. Per il momento LenRecord+1 ottiene il numero corretto di byte da scrivere nel file.

ti posto tutto il codice visto che le parti interessate potrebbero essere diverse. Se guardi solo il main tuttosommato è corto.
Attenzione!!! Non pretendo che leggi tutte le 300 righe, lo posto solo perchè puoi guardare solo i punti che ritieni utili a risolvere il problema.

La logica del programma si riassume così:
I file che accodo (in questo caso 2) sono file afp. Si tratta di file contenente record così composti:
- un byte fisso (in esadecimale 5A)
- due byte che indicano la lunghezza dell'intero record
- tre byte che indicano il tipo di record
- contenuto del record vero e proprio

in sostanza devo unire i due file di input escludendo alcuni record



#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <windows.h>


const MaxFogliPerBusta=99;
struct StrutturaStatistica
{
long QtaBuste;
}Stat[MaxFogliPerBusta];


struct DescrizioneAfp
{
int QtaPerFile;
int QtaBuste;
char *NomeFile;
}*DescAfp;

char Percorso[]="B:\\999999\\";

char **ElencoFileInput;
int NumeroDiFile=0;
char *NomeFileOutput;
char *NomeFileStatistica;




//************************************************** *******************
// FUNZIONE PER CALCOLARE LA LUNGHEZZA DEL FILE
int get_filesize( char* filename )
{
struct stat file_info;
if( !stat( filename, &file_info ) )
return file_info.st_size;
return -1;
}
//
//__________________________________________________ __________________



//************************************************** *******************
// CONVERTITORE ASCII TO HEX
char* AsciiToHex(char* sAscii,int Lunghezza)
{
char *StringaEsadecimale, *Hex;
int i;

StringaEsadecimale=(char*)malloc(Lunghezza*2+1);
StringaEsadecimale[0]='\0';
Hex=(char*)malloc(sizeof(char)*1);
for(i=0;i<Lunghezza;i++)
{
itoa((unsigned char)sAscii[i],Hex,16);
//sprintf(Hex2,"%x",sAscii[i]);
//printf("%s",Hex2);
strcat(StringaEsadecimale,Hex);
}
return StringaEsadecimale;
}
//
//__________________________________________________ __________________



//************************************************** *******************
// FUNZIONE PER RICERCA DEI FILE AFP PRESENTI IN UNA CARTELLA
bool CreaListaFile()
{
char *sTmp;
WIN32_FIND_DATA fd;
HANDLE hFind;

sTmp=(char*)malloc(sizeof(char)*strlen(Percorso)+1 );
strcpy(sTmp,Percorso);
strcat(sTmp,"*.afp");

hFind=FindFirstFile(sTmp,&fd);
if(hFind==INVALID_HANDLE_VALUE)
{
fputs("Nessun file trovato o percorso inesistente.",stderr);
return false;
}

ElencoFileInput=(char**)malloc(sizeof(char*));
do
{
ElencoFileInput=(char**)realloc(ElencoFileInput,(N umeroDiFile+2)*sizeof(char*));
ElencoFileInput[NumeroDiFile]=(char*)malloc(strlen(fd.cFileName)*sizeof(char));
strcpy(ElencoFileInput[NumeroDiFile],fd.cFileName);
NumeroDiFile++;
} while(FindNextFile(hFind,&fd));
FindClose(hFind);

return true;
}
//
//__________________________________________________ __________________



//************************************************** *******************
// FUNZIONE PER IMPOSTARE IL NOME DEL FILE DI OUTPUT
void ImpostaNomeFileOutput()
{
char *sTmp,*sLast,*sPercorso;
sPercorso=(char*)malloc(sizeof(char)*strlen(Percor so)+1);
strcpy(sPercorso,Percorso);
sTmp=strtok(sPercorso,"\\");
sLast=(char*)malloc(sizeof(char)*strlen(sTmp)+1);
strcpy(sLast,sTmp);
while(sTmp!=NULL)
{
sLast=(char*)malloc(sizeof(char)*strlen(sTmp)+1);
strcpy(sLast,sTmp);
sTmp=strtok(NULL,"\\");
}
NomeFileOutput=(char*)malloc(strlen(Percorso) + strlen("\\") + strlen(sLast) + strlen(".AFP") + 1);
strcpy(NomeFileOutput,Percorso);
strcat(NomeFileOutput,"\\");
strcat(NomeFileOutput,sLast);
strcat(NomeFileOutput,".AFP");
}
//
//__________________________________________________ __________________



//************************************************** *******************
// FUNZIONE PER IMPOSTARE IL NOME DEL FILE STATISTICA
void ImpostaNomeFileStatistica()
{
char *sTmp,*sLast,*sPercorso;
sPercorso=(char*)malloc(sizeof(char)*strlen(Percor so)+1);
strcpy(sPercorso,Percorso);
sTmp=strtok(sPercorso,"\\");
sLast=(char*)malloc(sizeof(char)*strlen(sTmp)+1);
strcpy(sLast,sTmp);
while(sTmp!=NULL)
{
sLast=(char*)malloc(strlen(sTmp)+1);
strcpy(sLast,sTmp);
sTmp=strtok(NULL,"\\");
}
NomeFileStatistica=(char*)malloc(strlen(Percorso) + strlen("\\") + strlen(sLast) + strlen("_stat.txt") + 1);
strcpy(NomeFileStatistica,Percorso);
strcat(NomeFileStatistica,"\\");
strcat(NomeFileStatistica,sLast);
strcat(NomeFileStatistica,"_stat.txt");
}
//
//__________________________________________________ __________________



//************************************************** *******************
// FUNZIONE PER INIZIALIZZARE LA STRUTTURA STATISTICA
void InizializzaStrutturaStat()
{
for(int i=0;i<=MaxFogliPerBusta;i++)
{
Stat[i].QtaBuste=0;
}
}
//
//__________________________________________________ __________________



//************************************************** *******************
// FUNZIONE PER INIZIALIZZARE LA STRUTTURA DESCRIZIONE FILE
void InizializzaStrutturaDescAfp()
{
//printf("%d\n",sizeof(DescrizioneAfp));
DescAfp=(struct DescrizioneAfp*)malloc(sizeof(struct DescrizioneAfp)*(NumeroDiFile+1));
for(int i=0;i<NumeroDiFile;i++)
{
DescAfp[i].NomeFile=(char*)malloc(strlen(ElencoFileInput[i])+1);
strcpy(DescAfp[i].NomeFile,ElencoFileInput[i]);
DescAfp[i].QtaBuste=0;
DescAfp[i].QtaPerFile=0;
}
}
//
//__________________________________________________ __________________


void main(void)
{
FILE *fpi;
FILE *fpo;
int i;
int ContatoreFile;
int ParzialePagine=0;
int PagineTotali=0;
int TotBuste=0;
long ByteLetti=0;
long RecordAfp=0;
long LenRecord;
char *s5A;
char *NomeFileInput;
char *StrApp;
char *BufferRecord;
char *Record;
char *TipoRecord;
char *TipoRecordHex;
char TipoRecordBDT[] ="D3A8A8"; // begin document
char TipoRecordEDT[] ="D3A9A8"; // end document
char TipoRecordBPG[] ="D3A8AF"; // begin page
char TipoRecordEPG[] ="D3A9AF"; // end page
char TipoRecordBNG[] ="D3A8AD"; // begin named page group
char TipoRecordENG[] ="D3A9AD"; // end named page group


bool ScriviRecord;
StrutturaStatistica StatFile[MaxFogliPerBusta];


CreaListaFile();
ImpostaNomeFileOutput();
ImpostaNomeFileStatistica();
InizializzaStrutturaStat();
InizializzaStrutturaDescAfp();

s5A=(char*)malloc(1);

fpo=fopen(NomeFileOutput,"wb");
for(ContatoreFile=0;ContatoreFile<NumeroDiFile;ContatoreFile++)
{
RecordAfp=0;
ParzialePagine=0;
for (i=0;i<=MaxFogliPerBusta;i++)
{
StatFile[i].QtaBuste=0;
}

NomeFileInput=(char*)malloc(strlen(Percorso) + strlen(ElencoFileInput[ContatoreFile]) + 1);
strcpy(NomeFileInput,Percorso);
strcat(NomeFileInput,ElencoFileInput[ContatoreFile]);
ByteLetti=0;
fpi=fopen(NomeFileInput,"rb");

while((!feof(fpi)) && (get_filesize(ElencoFileInput[ContatoreFile])<ByteLetti))
{
//inizio record 5a, leggo un byte e mi aspetto il 5A
RecordAfp++;
ScriviRecord=true;
fread(s5A,1,1,fpi);
ByteLetti++;
if(s5A[0]!='\x5A')
{
printf("manca 5A al record afp n. %d del file %s\n",RecordAfp,ElencoFileInput[ContatoreFile]);
return;
}

//calcolo la lunghezza del record 5A e inizio a riempire il buffer di output
StrApp=(char*)malloc(2);
fread(StrApp,2,1,fpi);
ByteLetti+=2;
LenRecord=(unsigned char)StrApp[0]*256+(unsigned char)StrApp[1];
BufferRecord=(char*)malloc(sizeof(char)*(3 + LenRecord));
//printf("%c\n",StrApp[0]);
//printf("%c\n",BufferRecord[0]);
BufferRecord[0]=s5A[0];
BufferRecord[1]=StrApp[0];
BufferRecord[2]=StrApp[1];

//leggo tutto il record 5A
Record=(char*)malloc(LenRecord-2);
fread(Record,(LenRecord-2),1,fpi);
ByteLetti+=sizeof(Record);

//trovo il tipo record 5A
TipoRecord=(char*)malloc(3);
TipoRecordHex=(char*)malloc(7);
TipoRecord[0]=Record[0];
TipoRecord[1]=Record[1];
TipoRecord[2]=Record[2];
TipoRecordHex=AsciiToHex(TipoRecord,3);

//faccio varie operazioni a seconda del record 5A
if(stricmp(TipoRecordHex,TipoRecordBDT)==0) //inizio del file. Solo se è il primo file allora scrivo il record
{
for(i=0;i<LenRecord-2;i++)
BufferRecord[i+3]=Record[i];
if(ContatoreFile>0)
ScriviRecord=false;
}
else if(stricmp(TipoRecordHex,TipoRecordEDT)==0) //fine del file. Solo se è l'ultimo file allora scrivo il record
{
for(i=0;i<LenRecord-2;i++)
BufferRecord[i+3]=Record[i];
if(ContatoreFile<(NumeroDiFile-1))
ScriviRecord=false;
}
else if(stricmp(TipoRecordHex,TipoRecordBPG)==0) //nuova pagina, conto le pagine di ogni file
{
for(i=0;i<LenRecord-2;i++)
BufferRecord[i+3]=Record[i];
DescAfp[ContatoreFile].QtaPerFile++;
PagineTotali++;
}
else if(stricmp(TipoRecordHex,TipoRecordEPG)==0) //fine pagina
{
for(i=0;i<LenRecord-2;i++)
BufferRecord[i+3]=Record[i];
ParzialePagine++;
}
else if(stricmp(TipoRecordHex,TipoRecordBNG)==0) //nuova anagrafica
{
for(i=0;i<LenRecord-2;i++)
BufferRecord[i+3]=Record[i];
DescAfp[ContatoreFile].QtaBuste++;
TotBuste++;
}
else if(stricmp(TipoRecordHex,TipoRecordENG)==0) //fine anagrafica
{
for(i=0;i<LenRecord-2;i++)
BufferRecord[i+3]=Record[i];
if(ParzialePagine%2!=0)
{
puts("Pagine non pari");
return;
}
Stat[ParzialePagine/2].QtaBuste++;
StatFile[ParzialePagine/2].QtaBuste++;
ParzialePagine=0;
}
else
{
for(i=0;i<LenRecord-2;i++)
BufferRecord[i+3]=Record[i];
}

// scrivo il record nel file
if(ScriviRecord==true)
{
fwrite(BufferRecord,LenRecord+1,1,fpo);
}
}
fclose(fpi);
}
fcloseall();
}

Loading