Valutazione 4.87/ 5 (100.00%) 5838 voti

Condividi:        

Problema Visual C++

Hai problemi con i file Zip, vuoi formattare l'HD, non sai come funziona FireFox? O magari ti serve proprio quel programmino di cui non ricordi il nome! Ecco il forum dove poter risolvere i tuoi problemi.

Moderatori: Dylan666, hydra, gahan

Problema Visual C++

Postdi infinito1971 » 04/12/02 21:42

Ciao a tutti,
sto impazzendo col seguente problema: leggere correttamente un file binario con Visual C++; la subroutine che ho realizzato è la seguente:

void CaricaFile(CString Nome)
{
CStdioFile oFile;
CString c;
oFile.Open(Nome, CFile::typeBinary | CFile::modeRead);
while (oFile.ReadString(c))
m_sTesto+=c;
oFile.Close();
}

Sebbene il compilatore non mi segnali errori di sorta, il file non viene letto, o per meglio dire immagazzinato nella variabile globale di tipo CString m_sTesto, in modo corretto.
Qualcuno sa darmi una mano?? Ci conto! ;)

Bye,
infinito1971
Avatar utente
infinito1971
Utente Senior
 
Post: 531
Iscritto il: 01/08/02 21:22
Località: Napoli

Sponsor
 

Postdi zello » 04/12/02 23:28

sorry, non conosco le MFC.
Ma, a pelo: una stringa (sicuramente una std::string dell'ansi, probabilmente una CString di MFC) è zero-terminated: vale a dire che se nel tuo bel file binario c'è uno zero, la lettura viene interrotta in quel punto.
Usa un array di unsigned char, da dimensionarsi dinamicamente in base alla dimensione del file.

HTH, HAND
Il faut être toujours ivre. Tout est là : c'est l'unique question. Pour ne pas sentir l'horrible fardeau du Temps qui brise vos épaules et vous penche vers la terre,il faut vous enivrer sans trêve...
Avatar utente
zello
Moderatore
 
Post: 2351
Iscritto il: 06/05/02 13:44

Postdi matteo baccan » 05/12/02 11:18

Purtroppo non segnali il problema che ottieni, o meglio, non so cosa trovi nella variabile CString dopo il ciclo di lettura.
Vediamo di controllare "a naso" quale potrebbe essere il problema

Prima di tutto apri un file in binario .. credo per averne il suo esatto contenuto ed evitare che ci possano essere strane conversioneda parte della classe di IO

Poi fai una ReadString, metodo che legge fino a che non trova un accapo nel file .. operazione che potrebbe essere voluta, nel caso di un file di testo, ma sicuramente non voluta nel caso di un file con contenuti non testuali .. vedi un immagine, un exe .. un avi ... un doc .. insomma, ma maggior parte dei casi

Fatto questo aggiungi alla string m_sTesto la stringa letta .. o meglio, quello che restituisce readstring dopo il troncamento sull'accapo o su eventuali caratteri 0 che vengono incontrati ...

A naso potresti avere i seguenti problemi

1) Fine non trovato: non controlli questa cosa, viene generata un eccezione, non ne fai un catch .. chissa' chi e come la gestisce ... perdiamo il contollo di flusso, nessun risultato

2) Leggi un binario, il file viene ripetutamente troncato/violentato da readstring, e accodato in maniera quasi randomica sul m_sTesto

3) Leggi un file ascii, il risultato e' quasi corretto, ma non ti trovi gli accapo che vengono tolti da ReadString

....

osservazioni varie ...

se vuoi fare in fretta, dato che diponiamo di memoria in abbondanza .. perche' non vedi quanto e' grosso il file e fai una sola READDONA di tutto il file in una botta sola???

...

spero che queste poche righe ti aiutino .. non ho VC sotto mano al momento e non posso fare di piu'

ciaooooooooooo

e fammi sapere com'e' andata
matteo baccan
Newbie
 
Post: 3
Iscritto il: 16/07/02 08:10

Postdi infinito1971 » 05/12/02 11:33

Ciao Matteo,
ti ringrazio moltissimo per il tuo intervento e, con grande esperienza, hai centrato esattamente il problema da me riscontrato (il punto 2 e, anche se non ho controllato, probabilmente anche il punto 3).
Ora, conoscendo la lunghezza del file, che posso recuperare con oFile.GetLenght(), come posso leggere tutto il file in un solo colpo e metterne il risultato nella variabile di classe CString?

A presto,
infinito1971
Avatar utente
infinito1971
Utente Senior
 
Post: 531
Iscritto il: 01/08/02 21:22
Località: Napoli

Postdi zello » 05/12/02 11:48

Al volo, sempre premettendo che non conosco CString: perché metti un file binario (che non contiene stringhe) in un CString? Non è meglio metterlo in un array di bytes (nel senso di unsigned char)?
Io - senza MFC - farei così:
Codice: Seleziona tutto
#include <windows.h>
#include <stdexcept>

using std::runtime_error;

BYTE* lpBuf=NULL;
void CaricaFile(const char* nome)throw(exception)
{
    HANDLE hFile=CreateFile(nome,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
    if(hFile==INVALID_HANDLE_VALUE)
       throw runtime_error("Cannot open file");
    DWORD dwSize=GetFileSize(hFile,NULL);
    delete[] lpBuf; //delete on NULL non sortisce nessun effetto
    lpBuf=new BYTE[dwSize];
    DWORD dwRead;
    if(!ReadFile(hFile,buf,dwSize,&dwRead,NULL))
         throw runtime_error("Cannot read file");
    CloseHandle(hFile);
}


Ricordati di fare un delete[] lpBuf prima di uscire dal programma, oppure usa uno smart pointer (tipo un std::auto_ptr<BYTE>).
Il faut être toujours ivre. Tout est là : c'est l'unique question. Pour ne pas sentir l'horrible fardeau du Temps qui brise vos épaules et vous penche vers la terre,il faut vous enivrer sans trêve...
Avatar utente
zello
Moderatore
 
Post: 2351
Iscritto il: 06/05/02 13:44

Classe CString

Postdi infinito1971 » 05/12/02 12:49

Ciao zello,
ringrazio molto anche te per l'aiuto ma purtroppo ho necessariamente (o quasi) bisogno di utilizzare la variabile di tipo CString...

A presto,
infinito1971
Avatar utente
infinito1971
Utente Senior
 
Post: 531
Iscritto il: 01/08/02 21:22
Località: Napoli

Postdi matteo baccan » 05/12/02 15:42

Zello ha proposto un ottimo codice ... non l'ho provato, ma confido che funzioni.

Partendo da questo, potresti provare a fare qualcosa di molto simile a

...
CaricaFile( "porcheria.jpg" );
...
CString monnezza( lpBuf );

ma credo che comunque il costruttore di CString faccia una strlen() del parametro, quindi lo beccheresti fino al primo 0.

Potresti pero' provare a fare un paio di modifiche

1) Cambiare lo Zello code in modo che torni il numero di byte letti dal file

long CaricaFile( etc etc etc

2) Usare questo valore nel costruttore di CString

long nLen = CaricaFile( "porcheria.jpg" );
CString monnezza( lpBuf, nLen );

l'unico particolare e' che. .. non ricordo .. se puoi passare la len della stringa a CString .. inoltre, ipotizzando di riuscirci ... dovresti usare il CString accedendo direttamente al suo buffer .. non ricordo se e come ..., altrimenti rischieresti ulteriori azzeramenti ...

come dicevo ... non ho il visual sotto le mani .. quindi queste sono solo idee e non certezze

lunga vita e prosperita'
matteo baccan
Newbie
 
Post: 3
Iscritto il: 16/07/02 08:10

Problema risolto!

Postdi infinito1971 » 05/12/02 22:35

Innanzitutto vorrei dire un enorme grazie a Zello e a Matteo Baccan.
I vostri suggerimenti sono stati preziosissimi ed illuminanti!
Il vero problema stava nel fatto di voler "costringere" un file binario in una variabile di tipo CString: non c'era modo di uscirne; allora ho seguito il consiglio di Zello: ho utilizzato una variabile di tipo char* e tutto è diventato più semplice...
Alla fine il codice che ho scritto è stato il seguente:

char* CaricaFile(CString Nome)
{
CFile oFile;
char* Buffer;

oFile.Open(Nome, CFile::typeBinary | CFile::modeRead);
m_nLunghezzaFile=oFile.GetLength();
Buffer=(char*)malloc(m_nLunghezzaFile);
oFile.Read(Buffer,m_nLunghezzaFile);
oFile.Close();

return Buffer;
}


Grazie a tutti! :)

Saluti,
infinito1971
Avatar utente
infinito1971
Utente Senior
 
Post: 531
Iscritto il: 01/08/02 21:22
Località: Napoli

Postdi zello » 06/12/02 08:33

Due appuntini, più un parere personale che un vero consiglio:
1) sei in C++, usa il C++. Non usare malloc, usa new.
invece di:
Buffer=(char*)malloc(m_nLunghezzaFile);
scrivi
Buffer=new char[m_nLunghezzaFile];
2) controlla che da qualche parte Buffer venga rilasciato, senno' hai dei memory leaks. Naturalmente, dove fai
free(Buffer);
sostituisci per coerenza con
delete[] Buffer;

Ciao
Il faut être toujours ivre. Tout est là : c'est l'unique question. Pour ne pas sentir l'horrible fardeau du Temps qui brise vos épaules et vous penche vers la terre,il faut vous enivrer sans trêve...
Avatar utente
zello
Moderatore
 
Post: 2351
Iscritto il: 06/05/02 13:44

Miglioramenti al codice...

Postdi infinito1971 » 06/12/02 09:34

Grazie Zello,
i tuoi interventi sono sempre preziosissimi!
Per il primo punto eseguirò senz'altro la modifica; per il secondo ci avevo già pensato in quanto è ben noto che Visual C++ non dispone di un garbage collector...

Alla prossima,
infinito1971
Avatar utente
infinito1971
Utente Senior
 
Post: 531
Iscritto il: 01/08/02 21:22
Località: Napoli


Torna a Software Windows


Topic correlati a "Problema Visual C++":


Chi c’è in linea

Visitano il forum: Nessuno e 16 ospiti